CUDA三重循环

时间:2015-04-14 15:31:25

标签: c for-loop cuda

我对CUDA很陌生,而且我很难将C代码转换为CUDA C,它成功构建但是它一直在崩溃。三重循环功能肯定是错误的,我不知道应该改变什么。

函数调用:

for (z=0;z<=max;z++)    
    {
    correlationsum=coefficient(x, n, dim, z);
    printf("result for epsilon %d returns %d\n", z, correlation_sum);
    }    

功能

long coefficient(int vctr[40000], long numberofpoints, int coefficientrow, int epsilon)
{
long i, j, k, sum, numberofpairs;
long sq_epsilon;
sq_epsilon=epsilon*epsilon;
numberofpairs=0;
for (i=1;i<=numberofpoints-coefficientrow;i++)
    {
    sum=0;
    for (j=i+1;j<=numberofpoints+1-coefficientrow;j++)
        {
        for (k=0;k<coefficientrow;k++)
            {
            sum=sum+(vctr[i+k]-vctr[j+k])*(vctr[i+k]-vctr[j+k]);                
            }
        if(sum<sq_epsilon)  
            {
            numberofpairs++;
            sum=0;
            }
        }
    }
return (numberofpairs);
}

我在GPU部分中限制功能时遇到了问题,所以它没有超出范围(例如k小于上面的系数)。我看到可以分配块/线程并使用if函数。我已经尝试了但是在三重循环中它有点......奇怪。

这几乎是完整的代码。

    #define THREADS 1024
__global__ void coefficient(int *vctr, int numberofpoints, int coefficient_row, int epsilon, int *numbofpairs){
        int i = blockIdx.x * blockDim.x + threadIdx.x;
        int j = blockIdx.y * blockDim.y + threadIdx.y;
        int k = blockIdx.z * blockDim.z + threadIdx.z;
        int sum;
        numbofpairs = 0;
        int sq_epsilon = epsilon*epsilon;


        if (i <= numberofpoints - coefficient_row)
        {
            sum = 0;
            if (j <= numberofpoints + 1 - coefficient_row)
            {
                if (k < coefficient_row)
                    sum = sum + (vctr[i + k] - vctr[j + k])*(vctr[i + k] - vctr[j + k]);
                if (sum < sq_epsilon){
                    numbofpairs++;
                    sum = 0;
    }}}}    

int main()
{
int n, dim, max, z;
int *d_n, *d_dim, *d_z, *d_x, *d_numbofpairs;
int x[40000], correlation_sum = 0;
    n=10;  
    max=10;
    dim=3;  

    cudaMalloc((void **)&d_n, sizeof(int));
    cudaMalloc((void **)&d_dim, sizeof(int));
    cudaMalloc((void **)&d_z, sizeof(int));
    cudaMalloc((void **)&d_x, sizeof(int));
    cudaMalloc((void **)&d_numbofpairs, sizeof(int));

    cudaMemcpy(d_n, &n, sizeof(int), cudaMemcpyHostToDevice);
    cudaMemcpy(d_dim, &dim, sizeof(int), cudaMemcpyHostToDevice);
    cudaMemcpy(d_x, &x, sizeof(int), cudaMemcpyHostToDevice);

    for (z = 0; z <= max; z++)
    {
        cudaMemcpy(d_z, &z, sizeof(int), cudaMemcpyHostToDevice);
        coefficient << <1, THREADS >> >(d_x, *d_n, *d_dim, *d_z, d_numbofpairs);
        cudaMemcpy(&correlation_sum, d_numbofpairs, sizeof(int), cudaMemcpyDeviceToHost);
        printf("result for epsilon %d returns %d\n", z, correlation_sum);
    }
    cudaFree(d_n);
    cudaFree(d_dim);
    cudaFree(d_z);
    cudaFree(d_x);
    cudaFree(d_numbofpairs);
    return 0;
}

我想要一些帮助或提示要改变什么,出了什么问题以及为什么它会一直崩溃所以我可以解决它。谢谢!

编辑:我完成了一些部分,抱歉我的不好。至于线程和块,我很困惑,GPU每块显示1024个线程,我不知道它是否是它。

1 个答案:

答案 0 :(得分:2)

所以“崩溃”是一个段错误。 seg故障是主机代码中的问题,而不是内核代码(尽管它可能在您使用CUDA API时)。

您的代码存在各种问题。

  1. 这可能会造成麻烦:

    int x[40000]
    

    这会创建一个基于堆栈的大型分配。相反,我建议进行动态分配:

    int *x = (int *)malloc(40000*sizeof(int));
    

    动态分配的尺寸限制要大得多。

  2. 从内核使用情况来看,您打算使用整个x向量。因此,d_x设备上的此分配不正确:

    cudaMalloc((void **)&d_x, sizeof(int));
    

    我们需要在设备上使用与主机上相同的大小分配:

    cudaMalloc((void **)&d_x, 40000*sizeof(int));
    
  3. 对应于2,您可能希望将整个x向量复制到设备(由于您的代码未显示x的初始化,因此不太清楚),< em>和您错误地在此处获取了x的地址,但x 已经指针:

    cudaMemcpy(d_x, &x, sizeof(int), cudaMemcpyHostToDevice);
    

    所以我们想要这样的东西:

    cudaMemcpy(d_x, x, 40000*sizeof(int), cudaMemcpyHostToDevice);
    
  4. 您的其他内核参数似乎是标量参数。你大部分时间都处理错误:

    __global__ void coefficient(int *vctr, int numberofpoints, int coefficient_row, int epsilon, int *numbofpairs){
    

    对于像上面指定的numberofpoints这样的参数(单向传递给函数),我们只需传递值调用内核时所需的主机数量,就像我们想的那样具有普通的C功能。所以这个内核调用不正确(即使它似乎编译):

    coefficient << <1, THREADS >> >(d_x, *d_n, *d_dim, *d_z, d_numbofpairs);
    

    相反,我们想通过值传递主机变量:

    coefficient << <1, THREADS >> >(d_x, n, dim, z, d_numbofpairs);
    

    由于d_numbofpairs正在双向进行,因此您的使用是正确的。

  5. 我还建议您在代码中添加proper cuda error checking

  6. 这是一个完整的例子,修复了上述错误。我认为结果当然是假的,因为输入数据(例如x)没有初始化。

    $ cat t724.cu
    #include <stdio.h>
    
    #define cudaCheckErrors(msg) \
        do { \
            cudaError_t __err = cudaGetLastError(); \
            if (__err != cudaSuccess) { \
                fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                    msg, cudaGetErrorString(__err), \
                    __FILE__, __LINE__); \
                fprintf(stderr, "*** FAILED - ABORTING\n"); \
                exit(1); \
            } \
        } while (0)
    
    
    #define THREADS 1024
    
    __global__ void coefficient(int *vctr, int numberofpoints, int coefficient_row, int epsilon, int *numbofpairs){
            int i = blockIdx.x * blockDim.x + threadIdx.x;
            int j = blockIdx.y * blockDim.y + threadIdx.y;
            int k = blockIdx.z * blockDim.z + threadIdx.z;
            int sum;
            numbofpairs = 0;
            int sq_epsilon = epsilon*epsilon;
    
    
            if (i <= numberofpoints - coefficient_row)
            {
                sum = 0;
                if (j <= numberofpoints + 1 - coefficient_row)
                {
                    if (k < coefficient_row)
                        sum = sum + (vctr[i + k] - vctr[j + k])*(vctr[i + k] - vctr[j + k]);
                    if (sum < sq_epsilon){
                        numbofpairs++;
                        sum = 0;
        }}}}
    
    int main()
    {
      int n, dim, max, z;
      int  *d_x, *d_numbofpairs;
      int correlation_sum = 0;
      int *x = (int *)malloc(40000*sizeof(int));
      if (x == NULL) {printf("malloc fail\n"); return -1;}
        n=10;
        max=10;
        dim=3;
    
        cudaMalloc((void **)&d_x, sizeof(int));
        cudaCheckErrors("cudaMalloc 1 fail");
        cudaMalloc((void **)&d_numbofpairs, sizeof(int));
        cudaCheckErrors("cudaMalloc 2 fail");
        cudaMemcpy(d_x, x, sizeof(int), cudaMemcpyHostToDevice);
        cudaCheckErrors("cudaMemcpy 1 fail");
    
        for (z = 0; z <= max; z++)
        {
            coefficient << <1, THREADS >> >(d_x, n, dim, z, d_numbofpairs);
            cudaMemcpy(&correlation_sum, d_numbofpairs, sizeof(int), cudaMemcpyDeviceToHost);
            cudaCheckErrors("cudaMemcpy 2/kernel fail");
            printf("result for epsilon %d returns %d\n", z, correlation_sum);
        }
        cudaFree(d_x);
        cudaFree(d_numbofpairs);
        return 0;
    }
    $ nvcc -o t724 t724.cu
    $ ./t724
    result for epsilon 0 returns 3
    result for epsilon 1 returns 3
    result for epsilon 2 returns 3
    result for epsilon 3 returns 3
    result for epsilon 4 returns 3
    result for epsilon 5 returns 3
    result for epsilon 6 returns 3
    result for epsilon 7 returns 3
    result for epsilon 8 returns 3
    result for epsilon 9 returns 3
    result for epsilon 10 returns 3
    $
    

    请注意,我没有对您的内核代码进行任何更改。