c - 使用 CUDA 内核获取堆栈溢出

标签 c pointers cuda stack-overflow parallel-processing

我正在编写的代码有一个很大的问题。 我不是专家,来之前问过很多人。也纠正了很多东西。所以,我想我已经准备好向您展示代码并问您我的问题了。 我将把整个代码放在这里,作为一种让你很好地理解我的问题的方法。 我想做的是,如果 ARRAY_SIZE 对于 THREAD_SIZE 来说太大了,所以我将大数组的数据放入一个较小的数组中,该数组是专门创建的,大小为 THREAD_SIZE。 然后,我将它发送到内核并做任何我必须做的事情。但是我这边有问题

isub_matrix[x*THREAD_SIZE+y]=big_matrix[x*ARRAY_SIZE+y];

由于堆栈溢出,代码停止的地方。首先,我做了一个 big_matrix 的双指针。但是 freenode irc 网络的#cuda channel 中的人告诉我它太大了,CPU 内存无法处理它,我应该创建一个线性指针。我做到了,但我仍然有同样的堆栈溢出问题。所以,它开始了......经过一些更改后更新,但还没有工作(堆栈溢出停止,但链接和 list 更新失败)

#define ARRAY_SIZE 2048
#define THREAD_SIZE 32
#define PI 3.14


int main(int argc, char** argv) 
{
        int array_plus=0,x,y;
        float time;
        //unsigned int memsize=sizeof(float)*THREAD_SIZE*THREAD_SIZE;
        //bool array_rest;
        cudaEvent_t start,stop;
        float *d_isub_matrix;

    float *big_matrix = new float[ARRAY_SIZE*ARRAY_SIZE];
    float *big_matrix2 = new float[ARRAY_SIZE*ARRAY_SIZE];
    float *isub_matrix = new float[THREAD_SIZE*THREAD_SIZE];
    float *osub_matrix = new float[THREAD_SIZE*THREAD_SIZE];

        //if the array's size is not compatible with the thread's size, it won't work.

        //array_rest=(ARRAY_SIZE*ARRAY_SIZE)/(THREAD_SIZE*THREAD_SIZE);
        //isub_matrix=(float*) malloc(memsize);
        //osub_matrix=(float*) malloc(memsize);

        if(((ARRAY_SIZE*ARRAY_SIZE)%(THREAD_SIZE*THREAD_SIZE)==0))
        {

            //allocating space in CPU memory and GPU memory for the big matrix and its sub matrixes
            //it has to be like this (lots of loops)



            //populating the big array
            for(x=0;x<ARRAY_SIZE;x++)
            {
                for(y=0;y<ARRAY_SIZE;y++)
                    big_matrix[x*ARRAY_SIZE+y]=rand()%10000;
            }

            //kind of loop for the big array

            //Start counting the time of processing (everything)
            cudaEventCreate(&start);
            cudaEventCreate(&stop);

            cudaEventRecord(start,0);

            while(array_plus<ARRAY_SIZE)
            {

                //putting the big array's values into the sub-matrix

                for(x=0;x<THREAD_SIZE;x++)
                {
                    for(y=0;y<THREAD_SIZE;y++)
                        isub_matrix[x*THREAD_SIZE+y]=big_matrix[(x+array_plus)*ARRAY_SIZE+y];
                }

                cudaMalloc((void**)&d_isub_matrix,THREAD_SIZE*THREAD_SIZE*sizeof(float));
            cudaMalloc((void**)&osub_matrix,THREAD_SIZE*THREAD_SIZE*sizeof(float));
            cudaMemcpy(d_isub_matrix,isub_matrix,((THREAD_SIZE*THREAD_SIZE)*sizeof(float)),cudaMemcpyHostToDevice);

                //call the cuda kernel

                twiddle_factor<<<1,256>>>(isub_matrix,osub_matrix);//<----

                cudaMemcpy(osub_matrix,isub_matrix,((THREAD_SIZE*THREAD_SIZE)*sizeof(float)),cudaMemcpyDeviceToHost);

                array_plus=array_plus+THREAD_SIZE;
                for(x=0;x<THREAD_SIZE;x++)
                {
                    for(y=0;y<THREAD_SIZE;y++)
                        big_matrix2[x*THREAD_SIZE+array_plus+y]=osub_matrix[x*THREAD_SIZE+y];
                }

                array_rest=array_plus+(ARRAY_SIZE);

                cudaFree(isub_matrix);
                cudaFree(osub_matrix);
                system("PAUSE");
            }

            //Stop the time

            cudaEventRecord(stop,0);
            cudaEventSynchronize(stop);
            cudaEventElapsedTime(&time,start,stop);

            //Free memory in GPU




            printf("The processing time took... %fms to finish",time);
                    system("PAUSE");

        }
        printf("The processing time took...NAO ENTROU!");
        system("PAUSE");
        return 0;
}

//things to do: TRANSPOSITION!!!!

另一个问题是关于并行部分。 编译器 (Visual Studio) 说我一次使用了太多 pow() 和 exp()。 我该如何解决这个问题?

if((xIndex<THREAD_SIZE)&&(yIndex<THREAD_SIZE))
    {
        block[xIndex][yIndex]=exp(sum_sin[xIndex][yIndex])+exp(sum_cos[xIndex][yIndex]);
    }

原始代码在这里。我评论它是因为我想知道至少我的代码是否在 GPU 中发挥了一些值(value)。但它甚至没有启动内核......太伤心了)

__global__ void twiddle_factor(float *isub_matrix, float *osub_matrix)
{
    __shared__ float block[THREAD_SIZE][THREAD_SIZE];
    // int x,y,z;
    unsigned int xIndex = threadIdx.x;
    unsigned int yIndex = threadIdx.y;
    /*
    int sum_sines=0.0;
    int sum_cosines=0.0;
    float sum_sin[THREAD_SIZE],sum_cos[THREAD_SIZE];
    float angle=(2*PI)/THREAD_SIZE;

    //put into shared memory the FFT calculation (F(u))

    for(x=0;x<THREAD_SIZE;x++)
    {
        for(y=0;y<THREAD_SIZE;y++)
        {
            for(z=0;z<THREAD_SIZE;z++)
            {
                sum_sines=sum_sin+sin(isub_matrix[y*THREAD_SIZE+z]*(angle*z));
                sum_cosines=sum_cos+cos(isub_matrix[y*THREAD_SIZE+z]*(angle*z));

            }
            sum_sin[x][y]=sum_sines/THREAD_SIZE;
            sum_cos[x][y]=sum_cosines/THREAD_SIZE;

        }
    }
    */

    if((xIndex<THREAD_SIZE)&&(yIndex<THREAD_SIZE))
        block[xIndex][yIndex]=pow(THREAD_SIZE,0.5);

        //block[xIndex][yIndex]=pow(exp(sum_sin[xIndex*THREAD_SIZE+yIndex])+exp(sum_cos[xIndex*THREAD_SIZE+yIndex]),0.5);

        __syncthreads();

    //transposition X x Y
    //transfer back the results into another sub-matrix that is allocated in CPU

    if((xIndex<THREAD_SIZE)&&(yIndex<THREAD_SIZE))
            osub_matrix[yIndex*THREAD_SIZE+xIndex]=block[xIndex][yIndex];



    __syncthreads();
}

感谢阅读全文!

完整代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#define ARRAY_SIZE 2048
#define THREAD_SIZE 32
#define PI 3.14



__global__ void twiddle_factor(float *isub_matrix, float *osub_matrix)
{
    __shared__ float block[THREAD_SIZE][THREAD_SIZE];
    int x,y,z;
    unsigned int xIndex = threadIdx.x;
    unsigned int yIndex = threadIdx.y;

    float sum_sines=0.0;
    //float expo_sums;
    float sum_cosines=0.0;
    float sum_sin[THREAD_SIZE][THREAD_SIZE],sum_cos[THREAD_SIZE][THREAD_SIZE];
    float angle=(2*PI)/THREAD_SIZE;

    //put into shared memory the FFT calculation (F(u))

    for(x=0;x<THREAD_SIZE;x++)
    {
        for(y=0;y<THREAD_SIZE;y++)
        {
            for(z=0;z<THREAD_SIZE;z++)
            {
                sum_sines=sum_sines+sin(isub_matrix[y*THREAD_SIZE+z]*(angle*z));
                sum_cosines=sum_cosines+cos(isub_matrix[y*THREAD_SIZE+z]*(angle*z));

            }
            sum_sin[x][y]=sum_sines/THREAD_SIZE;
            sum_cos[x][y]=sum_cosines/THREAD_SIZE;

        }
    }


    if((xIndex<THREAD_SIZE)&&(yIndex<THREAD_SIZE))
    {
        block[xIndex][yIndex]=exp(sum_sin[xIndex][yIndex])+exp(sum_cos[xIndex][yIndex]);
    }




        __syncthreads();

    //transposition X x Y
    //transfer back the results into another sub-matrix that is allocated in CPU

    if((xIndex<THREAD_SIZE)&&(yIndex<THREAD_SIZE))
            osub_matrix[yIndex*THREAD_SIZE+xIndex]=block[xIndex][yIndex];



    __syncthreads();
}


int main(int argc, char** argv) 
{
        int array_plus=0,x,y;
        float time;
        //unsigned int memsize=sizeof(float)*THREAD_SIZE*THREAD_SIZE;
        //bool array_rest;
        cudaEvent_t start,stop;
        float *d_isub_matrix,*d_osub_matrix;

        float *big_matrix = new float[ARRAY_SIZE*ARRAY_SIZE];
        float *big_matrix2 = new float[ARRAY_SIZE*ARRAY_SIZE];
        float *isub_matrix = new float[THREAD_SIZE*THREAD_SIZE];
        float *osub_matrix = new float[THREAD_SIZE*THREAD_SIZE];

        //if the array's size is not compatible with the thread's size, it won't work.

        //array_rest=(ARRAY_SIZE*ARRAY_SIZE)/(THREAD_SIZE*THREAD_SIZE);
        //isub_matrix=(float*) malloc(memsize);
        //osub_matrix=(float*) malloc(memsize);

        if(((ARRAY_SIZE*ARRAY_SIZE)%(THREAD_SIZE*THREAD_SIZE)==0)&&(ARRAY_SIZE>=THREAD_SIZE))
        {

            //allocating space in CPU memory and GPU memory for the big matrix and its sub matrixes
            //it has to be like this (lots of loops)



            //populating the big array
            for(x=0;x<ARRAY_SIZE;x++)
            {
                for(y=0;y<ARRAY_SIZE;y++)
                    big_matrix[x*ARRAY_SIZE+y]=rand()%10000;
            }

            //kind of loop for the big array

            //Start counting the time of processing (everything)
            cudaEventCreate(&start);
            cudaEventCreate(&stop);

            cudaEventRecord(start,0);

            while(array_plus<ARRAY_SIZE)
            {

                //putting the big array's values into the sub-matrix

                for(x=0;x<THREAD_SIZE;x++)
                {
                    for(y=0;y<THREAD_SIZE;y++)
                        isub_matrix[x*THREAD_SIZE+y]=big_matrix[x*ARRAY_SIZE+y];
                }

                cudaMalloc((void**)&d_isub_matrix,THREAD_SIZE*THREAD_SIZE*sizeof(float));
                cudaMalloc((void**)&d_osub_matrix,THREAD_SIZE*THREAD_SIZE*sizeof(float));
                cudaMemcpy(d_isub_matrix,isub_matrix,((THREAD_SIZE*THREAD_SIZE)*sizeof(float)),cudaMemcpyHostToDevice);

                //call the cuda kernel

                twiddle_factor<<<1,256>>>(d_isub_matrix,d_osub_matrix);//<----

                cudaMemcpy(osub_matrix,d_osub_matrix,((THREAD_SIZE*THREAD_SIZE)*sizeof(float)),cudaMemcpyDeviceToHost);

                array_plus=array_plus+THREAD_SIZE;
                for(x=0;x<THREAD_SIZE;x++)
                {
                    for(y=0;y<THREAD_SIZE;y++)
                        big_matrix2[x*THREAD_SIZE+array_plus+y]=osub_matrix[x*THREAD_SIZE+y];
                }


                cudaFree(isub_matrix);
                cudaFree(osub_matrix);
                cudaFree(d_osub_matrix);
                cudaFree(d_isub_matrix);
            }

            //Stop the time

            cudaEventRecord(stop,0);
            cudaEventSynchronize(stop);
            cudaEventElapsedTime(&time,start,stop);

            //Free memory in GPU

最佳答案

我看到这段代码中有很多问题。

  1. 在将数据从 big_matrix 复制到 isub_matrix 之前,您没有为 isub_matrix 分配内存

        for(x=0;x<THREAD_SIZE;x++)
        {
            for(y=0;y<THREAD_SIZE;y++)
                isub_matrix[x*THREAD_SIZE+y]=big_matrix[x*ARRAY_SIZE+y];
        }
    
  2. 您没有为 isub_matrix 从主机到设备执行任何 cudaMemcpy。为isub_matrix在设备上分配内存后,需要复制数据。

  3. 我看到在 while 循环中您正在计算相同的数据。

            //putting the big array's values into the sub-matrix
    
            for(x=0;x<THREAD_SIZE;x++)
            {
                for(y=0;y<THREAD_SIZE;y++)
                    isub_matrix[x*THREAD_SIZE+y]=big_matrix[x*ARRAY_SIZE+y];
            }
    

for 循环应该依赖于 array_plus。

我建议你这样做

for(x=0;x<THREAD_SIZE;x++)
            {
                for(y=0;y<THREAD_SIZE;y++)
                    isub_matrix[x*THREAD_SIZE+y]=big_matrix[(x+array_plus)*ARRAY_SIZE+y];
            }
  1. 另外,我对array_rest的使用没有感觉。那是做什么用的?

基于更新的版本:

我看到的错误是

  1. 您正在使用 osub_matrix 作为主机和设备指针。我建议您创建另一个浮点指针并将其用于设备

float *d_osub_matrix;

cudaMalloc((void**)&d_osub_matrix,THREAD_SIZE*THREAD_SIZE*sizeof(float));

然后打电话。

twiddle_factor<<<1,256>>>(d_isub_matrix,d_osub_matrix);

然后做

cudaMemcpy(osub_matrix,d_osub_matrix, ((THREAD_SIZE*THREAD_SIZE)*sizeof(float)),cudaMemcpyDeviceToHost);
  1. 顺便说一句,它不是

    twiddle_factor<<<1,256>>>(isub_matrix,osub_matrix);

应该是

twiddle_factor<<<1,256>>>(d_isub_matrix,osub_matrix);

最终和完成的代码:

int main(int argc, char** argv)
{
        int array_plus=0,x,y;
        int array_plus_x, array_plus_y;
        float time;
        //unsigned int memsize=sizeof(float)*THREAD_SIZE*THREAD_SIZE;
        //bool array_rest;
        cudaEvent_t start,stop;
        float *d_isub_matrix,*d_osub_matrix;

        float *big_matrix = new float[ARRAY_SIZE*ARRAY_SIZE];
        float *big_matrix2 = new float[ARRAY_SIZE*ARRAY_SIZE];
        float *isub_matrix = new float[THREAD_SIZE*THREAD_SIZE];
        float *osub_matrix = new float[THREAD_SIZE*THREAD_SIZE];

        //if the array's size is not compatible with the thread's size, it won't work.

        //array_rest=(ARRAY_SIZE*ARRAY_SIZE)/(THREAD_SIZE*THREAD_SIZE);
        //isub_matrix=(float*) malloc(memsize);
        //osub_matrix=(float*) malloc(memsize);

        if(((ARRAY_SIZE*ARRAY_SIZE)%(THREAD_SIZE*THREAD_SIZE)==0)&&(ARRAY_SIZE>=THREAD_SIZE))
        {

            //allocating space in CPU memory and GPU memory for the big matrix and its sub matrixes
            //it has to be like this (lots of loops)



            //populating the big array
            for(x=0;x<ARRAY_SIZE;x++)
            {
                for(y=0;y<ARRAY_SIZE;y++)
                    big_matrix[x*ARRAY_SIZE+y]=rand()%10000;
            }

            //kind of loop for the big array

            //Start counting the time of processing (everything)
            cudaEventCreate(&start);
            cudaEventCreate(&stop);

            cudaEventRecord(start,0);
            for(array_plus_x = 0; array_plus_x < ARRAY_SIZE; array_plus_x += THREAD_SIZE)
            for(array_plus_y = 0; array_plus_y < ARRAY_SIZE; array_plus_y += THREAD_SIZE)
            {


                //putting the big array's values into the sub-matrix

                for(x=0;x<THREAD_SIZE;x++)
                {
                    for(y=0;y<THREAD_SIZE;y++)
                        isub_matrix[x*THREAD_SIZE+y]=big_matrix[(x+array_plus_x)*ARRAY_SIZE+(y+array_plus_y)];
                }

                cudaMalloc((void**)&d_isub_matrix,THREAD_SIZE*THREAD_SIZE*sizeof(float));
                cudaMalloc((void**)&d_osub_matrix,THREAD_SIZE*THREAD_SIZE*sizeof(float));
                cudaMemcpy(d_isub_matrix,isub_matrix,((THREAD_SIZE*THREAD_SIZE)*sizeof(float)),cudaMemcpyHostToDevice);

                //call the cuda kernel

                dim3 block(32,32);
                twiddle_factor<<<1,block>>>(d_isub_matrix,d_osub_matrix);//<----

                cudaMemcpy(osub_matrix,d_osub_matrix,((THREAD_SIZE*THREAD_SIZE)*sizeof(float)),cudaMemcpyDeviceToHost);

                for(x=0;x<THREAD_SIZE;x++)
                {
                    for(y=0;y<THREAD_SIZE;y++)
                        big_matrix2[(x+array_plus_x)*ARRAY_SIZE+(y+array_plus_y)]=osub_matrix[x*THREAD_SIZE+y];
                }

                cudaFree(d_osub_matrix);
                cudaFree(d_isub_matrix);
            }

            //Stop the time

            cudaEventRecord(stop,0);
            cudaEventSynchronize(stop);
            cudaEventElapsedTime(&time,start,stop);

            //Free memory in GPU

关于c - 使用 CUDA 内核获取堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8109307/

相关文章:

cuda - 在 "cheap"GPU 上为 CUDA 开发

c - struct 和 typedef 有什么区别?

c - 为什么常量的语法中没有符号字符?

c - 如何在C中使用while循环添加数组元素?

c - 了解指针取消引用和数组索引之间的区别

c - 使用结构体指针的指针进行 qsort

c - 地址分配中的问题

c++ - 两个单精度浮点 vector 的点积在 CUDA 内核中产生与在主机上不同的结果

c++ - 为什么在 for 循环内重复内核会使 CUDA 代码显着变慢?

c - 二分查找两个无符号整数