鱼C论坛

 找回密码
 立即注册
查看: 139|回复: 1

[已解决]cuda编程,很简单的累加运算,为啥核函数的调用会显示不允许

[复制链接]
发表于 2024-3-31 19:32:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
捕获.JPG
  1. //************************** *********************
  2. //         2024-3-17-
  3. // ************************** *********************
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <cuda_runtime.h>
  7. #include <device_launch_parameters.h>
  8. #include <string.h>
  9. //#include <device_functions.h>

  10. //使用全局内存来操作
  11. __global__ void global_reduce_kernel(float* d_out, float* d_in)
  12. {
  13.         int myId = threadIdx.x + blockIdx.x * blockDim.x;  //有多个block.在所有线程的位置
  14.         int tid = threadIdx.x;  //在当前block里面的位置

  15.         //在global memory里面做
  16.         //循环的条件是 s 大于 0,每次循环迭代结束后,s 的值右移一位(相当于将其除以 2),以便在下一次迭代中处理更小的数据块
  17.         for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
  18.         {
  19.                 if (tid < s)
  20.                 {
  21.                         d_in[myId] += d_in[myId + s];
  22.                 }
  23.                 __syncthreads();  //每个线程块每次循环结束之后才进行下一次运行
  24.         }

  25.         //最后要的是线程块的所有计算的求和结果
  26.         if (tid == 0)
  27.         {
  28.                 d_out[blockIdx.x] = d_in[myId];
  29.         }
  30. }


  31. //使用共享内存实现归约
  32. __global__ void share_reduce_kernel(float* d_out, float* d_in)
  33. {
  34.         extern __shared__ float sdata[];  //给每一个block定义他们各自的内存;

  35.         int myId = threadIdx.x + blockIdx.x * blockDim.x;  //有多个block.在所有线程的位置
  36.         int tid = threadIdx.x;  //在当前block里面的位置

  37.         //然后将全局内存的数据复制给共享内存, 之后就不需要再从全局内存读数据,
  38.         //共享数据读取的速度快于全局内存
  39.         sdata[tid] = d_in[myId];
  40.         __syncthreads();

  41.         for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
  42.         {
  43.                 if (tid < s)
  44.                 {
  45.                         d_in[myId] += d_in[myId + s];
  46.                 }
  47.                 __syncthreads();  //每个线程块每次循环结束之后才进行下一次运行
  48.         }

  49.         //最后要的是线程块的所有计算的求和结果
  50.         if (tid == 0)
  51.         {
  52.                 d_out[blockIdx.x] = d_in[myId];
  53.         }
  54. }

  55. void reduce(float* d_out, float* d_intermediate, float* d_in, int size, bool usesShareMemory)
  56. {
  57.         const int maxThreadsPerBlock = 1024;
  58.         int threads = maxThreadsPerBlock;
  59.         int blocks = size / maxThreadsPerBlock;

  60.         //这个地方对每个
  61.         if (usesShareMemory)
  62.         {
  63.                 share_reduce_kernel <<< blocks, threads, threads* sizeof(float) >>> (float* d_intermediate, float* d_in);
  64.         }
  65.         else
  66.         {
  67.                 global_reduce_kernel << < blocks, threads >> > (float* d_intermediate, float* d_in);
  68.         }

  69.         threads = blocks;
  70.         blocks = 1;
  71.         if (usesShareMemory)
  72.         {
  73.                 if (usesShareMemory)
  74.                 {
  75.                         share_reduce_kernel << < blocks, threads, threads * sizeof(float) >> > (float* d_intermediate, float* d_in);
  76.                 }
  77.                 else
  78.                 {
  79.                         global_reduce_kernel << < blocks, threads >> > (float* d_intermediate, float* d_in);
  80.                 }
  81.         }
  82. }


  83. int main(int argc, char** argv)
  84. {
  85.         int deviceCount;
  86.         cudaGetDeviceCount(&deviceCount);
  87.         if (deviceCount == 0)
  88.         {
  89.                 fprintf(stderr, "error: no device surporting\n");
  90.                 exit(EXIT_FAILURE);
  91.         }

  92.         int dev = 0;
  93.         cudaSetDevice(dev);

  94.         cudaDeviceProp devProps;
  95.         if (cudaGetDeviceProperties(&devProps, dev) == 0)
  96.         {
  97.                 printf("using device %d:\n,", dev);
  98.                 printf("%s: global memory: %dB; compute v%d.%d; clock: %d kHZ\n",
  99.                         devProps.name, (int)devProps.totalGlobalMem, (int)devProps.major, (int)devProps.major, (int)devProps.clockRate);
  100.         }

  101.         const int ARRAY_SIZE = 1 << 20;
  102.         const int ARRAY_BITE = ARRAY_SIZE * sizeof(float);

  103.         //在cpu上创建存储输入数据的数组
  104.         float h_in[ARRAY_SIZE];
  105.         float sum = 0.0f;
  106.         for (int i = 0; i < ARRAY_SIZE; i++)
  107.         {
  108.                 h_in[i] = -1.0f + (float)random() / ((float)RAND_MAX / 2.0f);
  109.                 sum += h_in[i];
  110.         }

  111.         //declare GPU memory pointers
  112.         float* d_in, *d_out, * d_intermediate;

  113.         //在GPU上创建存储待处理数据和处理结果的数组
  114.         cudaMalloc((void**)&d_in, ARRAY_BITE);
  115.         cudaMalloc((void**)&d_intermediate, ARRAY_BITE);
  116.         cudaMalloc((void**)&d_out, sizeof(float));

  117.         //将CPU输入数据输入到GPU
  118.         cudaMemcpy(d_in, h_in, ARRAY_BITE, cudaMemcpyHostToDevice);


  119.         int whichKernel = 0;
  120.         if (argc == 2)
  121.         {
  122.                 whichKernel = atoi(argv[1]);
  123.         }
  124. }


复制代码
最佳答案
2024-3-31 19:32:56
在你的代码中,出现了几个语法错误导致编译错误。我将逐个指出并给出修正后的代码。

首先,在`global_reduce_kernel`函数中,你想对全局内存的变量进行累加操作,但是你写成了`d_in += d_in`,这是错误的。应该使用`*d_in += *d_in`来对变量进行累加。此外,在最后的求和结果处,你写成了`d_out = d_in`,实际上应该是`*d_out = *d_in`。修正后的代码如下:

  1. __global__ void global_reduce_kernel(float* d_out, float* d_in)
  2. {
  3.     int myId = threadIdx.x + blockIdx.x * blockDim.x;
  4.     int tid = threadIdx.x;

  5.     for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
  6.     {
  7.         if (tid < s)
  8.         {
  9.             *d_in += *d_in;
  10.         }
  11.         __syncthreads();
  12.     }

  13.     if (tid == 0)
  14.     {
  15.         *d_out = *d_in;
  16.     }
  17. }
复制代码


接下来,在`share_reduce_kernel`函数中,你定义了一个共享内存`sdata`,但是你忘记给它分配实际的内存空间。共享内存的大小应该是每个线程块的大小(即`blockDim.x * sizeof(float)`)。修正后的代码如下:

  1. __global__ void share_reduce_kernel(float* d_out, float* d_in)
  2. {
  3.     extern __shared__ float sdata[];

  4.     int myId = threadIdx.x + blockIdx.x * blockDim.x;
  5.     int tid = threadIdx.x;

  6.     sdata[tid] = d_in[myId];
  7.     __syncthreads();

  8.     for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
  9.     {
  10.         if (tid < s)
  11.         {
  12.             sdata[tid] += sdata[tid + s];
  13.         }
  14.         __syncthreads();
  15.     }

  16.     if (tid == 0)
  17.     {
  18.         *d_out = sdata[0];
  19.     }
  20. }
复制代码


在`reduce`函数中,你调用核函数的方式不正确。应该使用`<<<...>>>`语法来调用核函数,并且传递的参数应该是设备端的指针。修正后的代码如下:

  1. void reduce(float* d_out, float* d_intermediate, float* d_in, int size, bool usesShareMemory)
  2. {
  3.     const int maxThreadsPerBlock = 1024;
  4.     int threads = maxThreadsPerBlock;
  5.     int blocks = size / maxThreadsPerBlock;

  6.     if (usesShareMemory)
  7.     {
  8.         share_reduce_kernel<<<blocks, threads, threads * sizeof(float)>>>(d_intermediate, d_in);
  9.     }
  10.     else
  11.     {
  12.         global_reduce_kernel<<<blocks, threads>>>(d_intermediate, d_in);
  13.     }

  14.     threads = blocks;
  15.     blocks = 1;
  16.     if (usesShareMemory)
  17.     {
  18.         if (usesShareMemory)
  19.         {
  20.             share_reduce_kernel<<<blocks, threads, threads * sizeof(float)>>>(d_out, d_intermediate);
  21.         }
  22.         else
  23.         {
  24.             global_reduce_kernel<<<blocks, threads>>>(d_out, d_intermediate);
  25.         }
  26.     }
  27. }
复制代码


最后,在`main`函数中,你定义了一个常量`ARRAY_SIZE`但没有给它赋值。请为它赋予一个合适的值,比如`1000`。修正后的代码如下:

  1. int main(int argc, char** argv)
  2. {
  3.     // ...

  4.     const int ARRAY_SIZE = 1000;

  5.     // ...
  6. }
复制代码


希望这些修正能够解决你遇到的问题。如果还有其他问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-3-31 19:32:56 | 显示全部楼层    本楼为最佳答案   
在你的代码中,出现了几个语法错误导致编译错误。我将逐个指出并给出修正后的代码。

首先,在`global_reduce_kernel`函数中,你想对全局内存的变量进行累加操作,但是你写成了`d_in += d_in`,这是错误的。应该使用`*d_in += *d_in`来对变量进行累加。此外,在最后的求和结果处,你写成了`d_out = d_in`,实际上应该是`*d_out = *d_in`。修正后的代码如下:

  1. __global__ void global_reduce_kernel(float* d_out, float* d_in)
  2. {
  3.     int myId = threadIdx.x + blockIdx.x * blockDim.x;
  4.     int tid = threadIdx.x;

  5.     for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
  6.     {
  7.         if (tid < s)
  8.         {
  9.             *d_in += *d_in;
  10.         }
  11.         __syncthreads();
  12.     }

  13.     if (tid == 0)
  14.     {
  15.         *d_out = *d_in;
  16.     }
  17. }
复制代码


接下来,在`share_reduce_kernel`函数中,你定义了一个共享内存`sdata`,但是你忘记给它分配实际的内存空间。共享内存的大小应该是每个线程块的大小(即`blockDim.x * sizeof(float)`)。修正后的代码如下:

  1. __global__ void share_reduce_kernel(float* d_out, float* d_in)
  2. {
  3.     extern __shared__ float sdata[];

  4.     int myId = threadIdx.x + blockIdx.x * blockDim.x;
  5.     int tid = threadIdx.x;

  6.     sdata[tid] = d_in[myId];
  7.     __syncthreads();

  8.     for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
  9.     {
  10.         if (tid < s)
  11.         {
  12.             sdata[tid] += sdata[tid + s];
  13.         }
  14.         __syncthreads();
  15.     }

  16.     if (tid == 0)
  17.     {
  18.         *d_out = sdata[0];
  19.     }
  20. }
复制代码


在`reduce`函数中,你调用核函数的方式不正确。应该使用`<<<...>>>`语法来调用核函数,并且传递的参数应该是设备端的指针。修正后的代码如下:

  1. void reduce(float* d_out, float* d_intermediate, float* d_in, int size, bool usesShareMemory)
  2. {
  3.     const int maxThreadsPerBlock = 1024;
  4.     int threads = maxThreadsPerBlock;
  5.     int blocks = size / maxThreadsPerBlock;

  6.     if (usesShareMemory)
  7.     {
  8.         share_reduce_kernel<<<blocks, threads, threads * sizeof(float)>>>(d_intermediate, d_in);
  9.     }
  10.     else
  11.     {
  12.         global_reduce_kernel<<<blocks, threads>>>(d_intermediate, d_in);
  13.     }

  14.     threads = blocks;
  15.     blocks = 1;
  16.     if (usesShareMemory)
  17.     {
  18.         if (usesShareMemory)
  19.         {
  20.             share_reduce_kernel<<<blocks, threads, threads * sizeof(float)>>>(d_out, d_intermediate);
  21.         }
  22.         else
  23.         {
  24.             global_reduce_kernel<<<blocks, threads>>>(d_out, d_intermediate);
  25.         }
  26.     }
  27. }
复制代码


最后,在`main`函数中,你定义了一个常量`ARRAY_SIZE`但没有给它赋值。请为它赋予一个合适的值,比如`1000`。修正后的代码如下:

  1. int main(int argc, char** argv)
  2. {
  3.     // ...

  4.     const int ARRAY_SIZE = 1000;

  5.     // ...
  6. }
复制代码


希望这些修正能够解决你遇到的问题。如果还有其他问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-1 07:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表