1

我正在尝试创建一个内部包含数组的数组结构并将它们加载到 GPU 上。我想我按照步骤正确地做到了这一点。

  1. 使用 malloc 在 CPU 上创建一个结构。
  2. cudamalloc数组到结构。
  3. 使用 cudamalloc 在 GPU 上创建结构
  4. 将 CPU 结构复制到 GPU 结构上。

当我运行此代码时,只要我不更改p[i].c[0]内核函数中的值,它就会正常工作。如果我删除该行p[i].c[0] = 3.3;,那么它会输出预期的结果。当我保持原样时,它会为所有值输出随机数。我希望能够使用内核函数更新数组中的值。

有什么问题?

这是我的代码:

#include <stdio.h>
#include <cuda_runtime.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <omp.h>
#include <vector>
#include <sys/time.h>

    float cData[]
                {
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10,
                        11,
                        12,
                        13,
                        14,
                        15,
                        16
                };
    float dData[]
                {
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10,
                        11,
                        12,
                        13,
                        14,
                        15,
                        16
                };

    typedef struct
            {
                float a, b;
                float* c;
                float* d;
            } point;

__global__ void testKernel(point *p){
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    p[i].a = 1.1;
    p[i].b = 2.2;
    p[i].c[0] = 3.3;
}

void checkerror(cudaError_t error, char* descrp){
    if (error != 0){

        printf("%s error code: %d \n", descrp, error);
    }

}

extern "C" int main()
{
    printf("starting gpuCode\n");
    int *dev_a;
            // set number of points
        int numPoints    = 16,
            gpuBlockSize = 4,
            pointSize    = sizeof(point),
            numBytes     = numPoints * pointSize,
            gpuGridSize  = numPoints / gpuBlockSize;
    cudaError_t err = cudaSuccess;
    printf("initialized variables\n");
            // allocate memory
        point *cpuPointArray,
              *gpuPointArray,
              *outPointArray;
        cpuPointArray = (point*)malloc(numBytes);  //create the cpuPointArray struct on the cpu
        outPointArray = (point*)malloc(numBytes);  //create the outPointArray struct on the cpu
        printf("load cpuPointArray struct with default values\n");

        for (int k=0; k<16; k++){
            err = cudaMalloc( (void**)&cpuPointArray[k].c, 16*sizeof(float) );
            checkerror(err, "assigning cuda pointer c");
            err = cudaMalloc( (void**)&cpuPointArray[k].d, 16*sizeof(float) );
            checkerror(err, "assigning cuda pointer d");
            cpuPointArray[k].a = 16;
            cpuPointArray[k].b = 16;
        }


        for (int k=0; k<16; k++){
            printf("top loop %d\n", k);
            err = cudaMemcpy(cpuPointArray[k].c, cData, 16*sizeof(float), cudaMemcpyHostToDevice);
            printf("after cdata\n");
            checkerror(err, "copying cdata to gpu array c" );
            err = cudaMemcpy(cpuPointArray[k].d, dData, 16*sizeof(float), cudaMemcpyHostToDevice);
            printf("after ddata\n");
            checkerror(err, "copying ddata to gpu array d");
            printf("bottom of loop %d\n", k);
        }

        err = cudaMalloc((void**)&gpuPointArray, numBytes);  //allocate memory on the gpu for the cpu point array
        checkerror(err, "allocating memory for gpuPointArray");
        err = cudaMemcpy(gpuPointArray,cpuPointArray,sizeof(cpuPointArray), cudaMemcpyHostToDevice); //copy the cpu point array onto the gpu
        checkerror(err, "copying cpuPointArray to gpuPointArray");

        printf("loaded the struct into the kernel\n");

        for(int i = 0; i < numPoints; ++i)
                {
                    printf("point.a: %f, point.b: %f ************************\n",cpuPointArray[i].a,cpuPointArray[i].b);

                        printf("cuda mem location point.c: %d point.d: %d\n",&cpuPointArray[i].c, &cpuPointArray[i].d);

                }

            // launch kernel
        testKernel<<<gpuGridSize,gpuBlockSize>>>(gpuPointArray);

        printf("returned the struct from the kernel\n");
        err = cudaMemcpy(outPointArray,gpuPointArray,numBytes, cudaMemcpyDeviceToHost);
        checkerror(err, "copying gpuPointArray to cpuPointArray");
        printf("after gpu copy to cpu\n");
        for (int k=0; k<16; k++){
            printf("creating memory on cpu for array c\n");
            outPointArray[k].c = (float*)malloc(16*sizeof(float));
            printf("creating memory on cpu for array d\n");
            outPointArray[k].d = (float*)malloc(16*sizeof(float));
            printf("copying memory values onto cpu array c\n");
            err = cudaMemcpy(outPointArray[k].c, cpuPointArray[k].c, 16*sizeof(float), cudaMemcpyDeviceToHost);
            checkerror(err, "copy array c from gpu to cpu");
            printf("copying memory values onto cpu array c\n");
            err = cudaMemcpy(outPointArray[k].d, cpuPointArray[k].d, 16*sizeof(float), cudaMemcpyDeviceToHost);
            checkerror(err, "copy array d from gpu to cpu");
            printf("bottom of loop %d\n", k);
        }

            // retrieve the results

        printf("testKernel results:\n");
        for(int i = 0; i < numPoints; ++i)
        {
            printf("point.a: %f, point.b: %f ************************\n",outPointArray[i].a,outPointArray[i].b);
            for (int j=0; j<16; j++){
                printf("point.c: %f point.d: %f\n",outPointArray[i].c[j], outPointArray[i].d[j]);
            }
        }

            // deallocate memory
        free(cpuPointArray);
        cudaFree(gpuPointArray);

        return 0;
    }
4

1 回答 1

1

似乎您可能错误地将结构数组复制到设备。尝试改变:

err = cudaMemcpy(gpuPointArray,cpuPointArray,sizeof(cpuPointArray), cudaMemcpyHostToDevice); 

成为

err = cudaMemcpy(gpuPointArray,cpuPointArray,numBytes, cudaMemcpyHostToDevice); 

因为 cpuPointArray 的类型是 point*,所以 sizeof(cpuPointArray) 实际上会返回机器上指针的大小。你想要的是整个结构数组的大小。事实上,从设备复制回来时,您甚至看起来都正确地执行了以下操作:

err = cudaMemcpy(outPointArray,gpuPointArray,numBytes, cudaMemcpyDeviceToHost);

希望有帮助!

于 2012-11-20T22:57:55.913 回答