CUDA深入浅出学习小结(1)
July 31st, 2010
No comments
平方和的并行计算
1. 直接分别使用CPU平方和, 一个Thread 一个Block的计算平方然后CPU计算平方和, 在10^7数据面前, CPU表示毫无压力(0cycle), 9600MGS惨不忍睹(多少cycles没记下)
2. 使用256个Threads后, GPU效率大大提升
3. 使用32blocks后, GPU再次提升效率
4. 此时已经有 32*256 = 8192 个线程在跑, 利用CPU计算和的时间被忽略造成不准确, 把计算和运算放在GPU中, 出现小幅性能下降
5. 计算sum可以并行化, 用树状图表示如下:
大意为第一次把1回到0上, 3加到2上, 因为所有线程都是要发起的, 对于判断哪些线程要执行加法很重要, 一个很简单想法是线程ID对offset的2倍取模看是否为0, 代码如下:
1 2 3 4 5 6 7 8 9 | __syncthreads(); //make sure all threads are complete extern __shared__ share[]; int offset=1 while( offset < THREADNUM ) //THREADNUM is the number of threads per block { if ( threadIdx.x%(offset+offset)==0 ) share[threadIdx.x] += share[threadIdx.x+offset]; offset += offset } |
然而时间并没有减少, 发现取模运算太费神, 在深入浅出书上如此写
1 2 3 4 5 6 7 8 9 10 | __syncthreads(); int offset = 1, mask = 1; while(offset < THREAD_NUM) { if((tid & mask) == 0) { // tid = threadIdx.x shared[tid] += shared[tid + offset]; } offset += offset; mask = offset + mask; __syncthreads(); } |
其中mask在里面的古怪作用正好使得結果如此…还是不太理解= =
6. 据说这方法会有问题..他说后面再说, 而采用另一种更简单方法, 大意是前半与后半相加不断递归…
1 2 3 4 5 6 7 8 | offset = THREAD_NUM >> 1; while(offset > 0) { if(tid < offset) { //tid = threadIdx.x shared[tid] += shared[tid + offset]; } offset >>= 1; __syncthreads(); } |
现在看求矩阵乘法了, cudaMemcpy 与 cudaMemcpy2D 区别还是没看懂… C语言2维数组与1维数组不是一样的…吗… int a[N*M] == int a[N][M] 那用cudaMemcpy 一下复制 N*M 不就得了…谁知道为何…

