Cuda计算点积

分手后的思念是犯贱 2022-03-17 08:56 269阅读 0赞

调试代码的过程中,发现了这样一个问题

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int test[10];
  6. cout << sizeof(test) << endl;
  7. float *a;
  8. //a = new float [10];
  9. cout << sizeof(a) << endl;
  10. int *b;
  11. b = new int (10);
  12. cout << sizeof(b) << endl;
  13. }

本以为直接指定数组大小和先生成指针再指定空间大小的sizeof()会是一样大的,结果不是一样大。

因为这个错误,在cuda c中调试了很久,最后终于发现是这里错了。


cuda c, 使用归约法求点积

有下面几个关键点:

1、指定block和thread的数量,不宜过少也不宜过多。

2、使用共享内存,一个线程块中每个线程都可以访问此共享内存

3、使用归约法,一个线程块中对线程求和的部分复杂度节约到了logn,不过线程数量应该是2的k次方,k为整数。

4、使用同步线程__syncthreads()


cuda c求一维数组点积源代码

  1. #include <iostream>
  2. #define imin(a, b) (a<b?a:b)
  3. #define sum_squares(x) (x*(x+1)*(2*x+1)/6) // 平方和
  4. using namespace std;
  5. const int N = 33 * 1024;
  6. const int threadsPerBlocks = 256;
  7. const int blocksPerGrid = imin(32, (N + threadsPerBlocks - 1) / threadsPerBlocks); // 向上取整获取线程块的数量
  8. __global__ void dot(float *a, float *b, float *c) { // 计算两个一维数组的点积
  9. int tid = threadIdx.x + blockIdx.x * blockDim.x;
  10. __shared__ float cache[threadsPerBlocks]; // 共享意味着在一个线程块里线程都可以访问这个数组
  11. int cacheIndex = threadIdx.x;
  12. float temp = 0;
  13. while (tid < N) {
  14. temp += a[tid] * b[tid];
  15. tid += gridDim.x * blockDim.x;
  16. }
  17. cache[cacheIndex] = temp; // 将所有的乘法结果聚集到一个grid(网格)里面
  18. __syncthreads(); // 直到上面的所有语句在所有线程里都执行结束才可以进行下面的语句,即为同步
  19. int i = threadsPerBlocks / 2;
  20. while (i != 0) { // 归约法,logn
  21. if (i > cacheIndex)
  22. cache[cacheIndex] += cache[cacheIndex + i];
  23. __syncthreads();
  24. i /= 2;
  25. }
  26. if (cacheIndex == 0)
  27. c[blockIdx.x] = cache[0];
  28. }
  29. int main() {
  30. float *a, *b, *partial_c, c;
  31. float *dev_a, *dev_b, *dev_partial_c;
  32. a = new float[N];
  33. b = new float[N];
  34. partial_c = new float[blocksPerGrid];
  35. cudaMalloc((void**)&dev_a, N * sizeof(float));
  36. cudaMalloc((void**)&dev_b, N * sizeof(float));
  37. cudaMalloc((void**)&dev_partial_c, blocksPerGrid * sizeof(float));
  38. for (int i = 0; i < N; ++i) {
  39. a[i] = i;
  40. b[i] = 2 * i;
  41. }
  42. cudaMemcpy(dev_a, a, N * sizeof(float), cudaMemcpyHostToDevice);
  43. cudaMemcpy(dev_b, b, N * sizeof(float), cudaMemcpyHostToDevice);
  44. dot << <blocksPerGrid, threadsPerBlocks >> > (dev_a, dev_b, dev_partial_c);
  45. cudaMemcpy(partial_c, dev_partial_c, blocksPerGrid * sizeof(float), cudaMemcpyDeviceToHost);
  46. c = 0.0;
  47. for (int i = 0; i < blocksPerGrid; ++i) {
  48. c += partial_c[i];
  49. }
  50. cout << c << " =? " << 2*(float)sum_squares(float(N - 1)) << endl;
  51. }

发表评论

表情:
评论列表 (有 0 条评论,269人围观)

还没有评论,来说两句吧...

相关阅读

    相关 CUDA 并行计算

    CUDA 并行计算 并行计算可以被定义为同时使用许多计算资源 (核心或计算机) 来执行并发计算,一个大的问题可以被分解成多个小问题,然后在不同的计算资源上并行处理这些小