source: CIVL/examples/translation/cuda/dot.cvl@ f6ce0eb

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

used civl's barrier implementation in cuda examples.

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

  • Property mode set to 100644
File size: 2.5 KB
Line 
1/* dot product of two arrays.
2 * Command line execution:
3 *
4 */
5#include <civlc.h>
6#include <stdio.h>
7
8#define imin(a,b) (a<b?a:b)
9
10$input int THREADS_PER_BLOCK; // thread number per block: must be a power of 2, due to the while loop at the end of gpuThread();
11$input int N_BOUND;
12$input int N;
13$assume 0 < N && N <= N_BOUND;
14int const threadsPerBlock = THREADS_PER_BLOCK;
15int const blocksPerGrid =
16 imin(32, (N+threadsPerBlock-1) / threadsPerBlock );
17double *a, *b, c, *partial_c;
18
19void gpu(){
20 $proc blocks[blocksPerGrid];
21
22 void gpuBlock(int blockID){
23 int num_in_barrier =0;
24 int barrier_size = 0;
25 double cache[threadsPerBlock];
26 $gbarrier gbarrier = $gbarrier_create($here, threadsPerBlock);
27 $proc threads[threadsPerBlock];
28
29 void gpuThread(int threadID){
30 int tid = threadID + blockID * threadsPerBlock;
31 int cacheIndex = threadID;
32 double temp = 0;
33 $barrier barrier = $barrier_create($here, gbarrier, threadID);
34
35 $atomic {
36 while (tid < N) {
37 temp += a[tid] * b[tid];
38 tid += threadsPerBlock * blocksPerGrid;
39 }
40 // set cache values
41 cache[cacheIndex] = temp;
42 }
43 // synchronize threads
44 $barrier_call(barrier);
45 int i = threadsPerBlock/2;
46 while (i != 0) {
47 if (cacheIndex < i)
48 cache[cacheIndex] += cache[cacheIndex + i];
49 // synchronize threads
50 $barrier_call(barrier);
51 i /= 2;
52 }
53 if (cacheIndex == 0)
54 partial_c[blockID] = cache[0];
55 $barrier_destroy(barrier);
56 }
57
58 for(int i = 0; i < threadsPerBlock; i++) {
59 threads[i] = $spawn gpuThread(i);
60 }
61 for(int i = 0; i < threadsPerBlock; i++) {
62 $wait(threads[i]);
63 }
64 $gbarrier_destroy(gbarrier);
65 }
66
67 for(int i = 0; i < blocksPerGrid; i++) {
68 blocks[i] = $spawn gpuBlock(i);
69 }
70 for(int i = 0; i < blocksPerGrid; i++) {
71 $wait(blocks[i]);
72 }
73}
74
75int main( void ) {
76 $scope host = $here;
77
78 // allocate memory on the cpu side
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;
86 }
87 gpu();
88 // finish up on the CPU side
89 c = 0;
90 for (int i=0; i<blocksPerGrid; i++) {
91 c += partial_c[i];
92 }
93 #define sum_squares(x) (x*(x+1)*(2*x+1)/6)
94 // check result
95 $assert(c == 2 * sum_squares( (double)(N - 1) ));
96 $free(a);
97 $free(b);
98 $free(partial_c);
99}
Note: See TracBrowser for help on using the repository browser.