source: CIVL/examples/cuda/dotProduct.cvl@ c46e702

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since c46e702 was 9c73065, checked in by Manchun Zheng <zmanchun@…>, 12 years ago

improved the POR algorithm, now it scales well.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@599 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 2.2 KB
RevLine 
[54d543c]1/* dot product of two arrays.
[9c73065]2 *
[54d543c]3 */
4#include <civlc.h>
5#include <stdio.h>
6
7#define imin(a,b) (a<b?a:b)
8
[0ebc1b0]9$input int BNPG;
[9c73065]10$input int K;
11$input int TNPB; // thread number per block: must be a power of 2
[0ebc1b0]12int N = (BNPG + 1) * K;
13int threadsPerBlock = TNPB;
14int blocksPerGrid =
15 imin(BNPG, (N+threadsPerBlock-1) / threadsPerBlock );
[54d543c]16double *a, *b, c, *partial_c;
17
18void gpu(){
19 void gpuBlock(int blockID){
20 #include "barrier.cvh"
21
22 double cache[threadsPerBlock];
23 int in_barrier[threadsPerBlock];
24
25 void gpuThread(int threadID){
26 int tid = threadID + blockID * threadsPerBlock;
27 int cacheIndex = threadID;
28 double temp = 0;
29
30 $atomic {
31 while (tid < N) {
32 temp += a[tid] * b[tid];
33 tid += threadsPerBlock * blocksPerGrid;
34 }
35 // set cache values
36 cache[cacheIndex] = temp;
37 }
[9c73065]38 // synchronize threads
[54d543c]39 barrier(in_barrier, threadID);
40 int i = threadsPerBlock/2;
41 while (i != 0) {
42 if (cacheIndex < i)
43 cache[cacheIndex] += cache[cacheIndex + i];
[9c73065]44 // synchronize threads
[54d543c]45 barrier(in_barrier, threadID);
46 i /= 2;
47 }
48 if (cacheIndex == 0)
49 partial_c[blockID] = cache[0];
50 }
51
52 $proc threads[threadsPerBlock];
[9c73065]53
54 barrier_init(in_barrier, threadsPerBlock);
55 for(int i = 0; i < threadsPerBlock; i++) {
56 threads[i] = $spawn gpuThread(i);
57 }
58
59 for(int i = 0; i < threadsPerBlock; i++) {
60 $wait threads[i];
[54d543c]61 }
62 }
63
[9c73065]64 $proc blocks[blocksPerGrid];
65
66 for(int i = 0; i < blocksPerGrid; i++) {
67 blocks[i] = $spawn gpuBlock(i);
68 }
69
70 for(int i = 0; i < blocksPerGrid; i++) {
71 $wait blocks[i];
72 }
[54d543c]73}
74
75int main( void ) {
76 $heap host;
77
78 // allocate memory on the cpu side
[77fc58c]79 a = (double *) $malloc(&host, N*sizeof(double));
80 b = (double *) $malloc(&host, N*sizeof(double));
81 partial_c = (double *) $malloc(&host, blocksPerGrid*sizeof(double));
82 // fill in the host memory with data
83 for (int i=0; i<N; i++) {
84 a[i] = i;
85 b[i] = i*2;
[54d543c]86 }
87 gpu();
[77fc58c]88 // finish up on the CPU side
89 c = 0;
90 for (int i=0; i<blocksPerGrid; i++) {
91 c += partial_c[i];
[54d543c]92 }
93 #define sum_squares(x) (x*(x+1)*(2*x+1)/6)
[de02f09]94 // check result
95 $assert(c == 2 * sum_squares( (double)(N - 1) ));
[54d543c]96}
Note: See TracBrowser for help on using the repository browser.