猪猪虾 发表于 2024-3-31 19:32:20

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


//************************** *********************
//         2024-3-17-
// ************************** *********************
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>
#include <string.h>
//#include <device_functions.h>

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

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

        //最后要的是线程块的所有计算的求和结果
        if (tid == 0)
        {
                d_out = d_in;
        }
}


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

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

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

        for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
        {
                if (tid < s)
                {
                        d_in += d_in;
                }
                __syncthreads();//每个线程块每次循环结束之后才进行下一次运行
        }

        //最后要的是线程块的所有计算的求和结果
        if (tid == 0)
        {
                d_out = d_in;
        }
}

void reduce(float* d_out, float* d_intermediate, float* d_in, int size, bool usesShareMemory)
{
        const int maxThreadsPerBlock = 1024;
        int threads = maxThreadsPerBlock;
        int blocks = size / maxThreadsPerBlock;

        //这个地方对每个
        if (usesShareMemory)
        {
                share_reduce_kernel <<< blocks, threads, threads* sizeof(float) >>> (float* d_intermediate, float* d_in);
        }
        else
        {
                global_reduce_kernel << < blocks, threads >> > (float* d_intermediate, float* d_in);
        }

        threads = blocks;
        blocks = 1;
        if (usesShareMemory)
        {
                if (usesShareMemory)
                {
                        share_reduce_kernel << < blocks, threads, threads * sizeof(float) >> > (float* d_intermediate, float* d_in);
                }
                else
                {
                        global_reduce_kernel << < blocks, threads >> > (float* d_intermediate, float* d_in);
                }
        }
}


int main(int argc, char** argv)
{
        int deviceCount;
        cudaGetDeviceCount(&deviceCount);
        if (deviceCount == 0)
        {
                fprintf(stderr, "error: no device surporting\n");
                exit(EXIT_FAILURE);
        }

        int dev = 0;
        cudaSetDevice(dev);

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

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

        //在cpu上创建存储输入数据的数组
        float h_in;
        float sum = 0.0f;
        for (int i = 0; i < ARRAY_SIZE; i++)
        {
                h_in = -1.0f + (float)random() / ((float)RAND_MAX / 2.0f);
                sum += h_in;
        }

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

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

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


        int whichKernel = 0;
        if (argc == 2)
        {
                whichKernel = atoi(argv);
        }
}


FishC 发表于 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`。修正后的代码如下:

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

    for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
    {
      if (tid < s)
      {
            *d_in += *d_in;
      }
      __syncthreads();
    }

    if (tid == 0)
    {
      *d_out = *d_in;
    }
}

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

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

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

    sdata = d_in;
    __syncthreads();

    for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1)
    {
      if (tid < s)
      {
            sdata += sdata;
      }
      __syncthreads();
    }

    if (tid == 0)
    {
      *d_out = sdata;
    }
}

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

void reduce(float* d_out, float* d_intermediate, float* d_in, int size, bool usesShareMemory)
{
    const int maxThreadsPerBlock = 1024;
    int threads = maxThreadsPerBlock;
    int blocks = size / maxThreadsPerBlock;

    if (usesShareMemory)
    {
      share_reduce_kernel<<<blocks, threads, threads * sizeof(float)>>>(d_intermediate, d_in);
    }
    else
    {
      global_reduce_kernel<<<blocks, threads>>>(d_intermediate, d_in);
    }

    threads = blocks;
    blocks = 1;
    if (usesShareMemory)
    {
      if (usesShareMemory)
      {
            share_reduce_kernel<<<blocks, threads, threads * sizeof(float)>>>(d_out, d_intermediate);
      }
      else
      {
            global_reduce_kernel<<<blocks, threads>>>(d_out, d_intermediate);
      }
    }
}

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

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

    const int ARRAY_SIZE = 1000;

    // ...
}

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: cuda编程,很简单的累加运算,为啥核函数的调用会显示不允许