与CUDA占用率计算器不同的实验结果

与CUDA占用率计算器不同的实验结果,cuda,Cuda,我学习CUDA建筑 我在如下环境中编写了一些并行处理代码 GPU:GTX580(CC为2.0) 每个块的线程数:16x16=256 每个线程的寄存器:16 每个块的共享内存:48字节 我通过compile选项知道寄存器的数量和共享内存的大小:--ptxas options=-v 此外,网格大小为32x32=1024,并且没有额外的共享内存 所以,我试着使用英伟达的CUDA_占用率_计算器。 然后说, 3.)GPU占用率数据显示在此处和图表中: 每个多处理器的活动线程数1536 每个多处理器的活动

我学习CUDA建筑

我在如下环境中编写了一些并行处理代码

GPU:GTX580(CC为2.0)

每个块的线程数:16x16=256

每个线程的寄存器:16

每个块的共享内存:48字节

我通过compile选项知道寄存器的数量和共享内存的大小:--ptxas options=-v 此外,网格大小为32x32=1024,并且没有额外的共享内存

所以,我试着使用英伟达的CUDA_占用率_计算器。 然后说,

3.)GPU占用率数据显示在此处和图表中: 每个多处理器的活动线程数1536 每个多处理器的活动扭曲48 每个多处理器的活动线程块6 每个多处理器的占用率100%

所以,我运行应用程序。 但是,结果显示块大小比16x16快8x8

8x8表示块大小,网格大小为64x64。 16x16表示块大小,网格大小为32x32。 因此,线程总数是相同的。没有变化

我不知道为什么。请帮帮我

下面的代码是我程序的一部分

void LOAD_VERTEX(){
        MEM[0] = 60;    //y0 
        MEM[1] = 50;    //x0
        MEM[2] = 128;   //r0
        MEM[3] = 0;     //g0
        MEM[4] = 70;    //b0
        MEM[5] = 260;
        MEM[6] = 50;
        MEM[7] = 135;
        MEM[8] = 70;
        MEM[9] = 0;
        MEM[10] = 260;
        MEM[11] = 250;
        MEM[12] = 0;
        MEM[13] = 200;
        MEM[14] = 55;
        MEM[15] = 60;
        MEM[16] = 250;
        MEM[17] = 55;
        MEM[18] = 182;
        MEM[19] = 100;
        MEM[20] = 30;
        MEM[21] = 330;
        MEM[22] = 72;
        MEM[23] = 12;
        MEM[24] = 25;
        MEM[25] = 30;
        MEM[26] = 130;
        MEM[27] = 80;
        MEM[28] = 255;
        MEM[29] = 15;
        MEM[30] = 230; 
        MEM[31] = 330;
        MEM[32] = 56;   
        MEM[33] = 186;  
        MEM[34] = 201;
}

__global__ void PRINT_POLYGON( unsigned char *IMAGEin, int *MEMin, int dev_ID, int a, int b, int c)
{
        int i = blockIdx.x*TILE_WIDTH + threadIdx.x;
        int j = blockIdx.y*TILE_HEIGHT + threadIdx.y;

        float result_a, result_b;
        int temp[15];
        int k;

        for(k = 0; k < 5; k++){
                temp[k] = a*5+k;
                temp[k+5] = b*5+k;
                temp[k+10] = c*5+k;
        }

        int result_a_up = ((MEMin[temp[11]]-MEMin[temp[1]])*(i-MEMin[temp[0]]))-((MEMin[temp[10]]-MEMin[temp[0]])*(j-MEMin[temp[1]]));
        int result_a_down = ((MEMin[temp[11]]-MEMin[temp[1]])*(MEMin[temp[5]]-MEMin[temp[0]]))-((MEMin[temp[6]]-MEMin[temp[1]])*(MEMin[temp[10]]-MEMin[temp[0]]));

        int result_b_up = ((MEMin[temp[6]] -MEMin[temp[1]])*(MEMin[temp[0]]-i))-((MEMin[temp[5]] -MEMin[temp[0]])*(MEMin[temp[1]]-j));
        int result_b_down = ((MEMin[temp[11]]-MEMin[temp[1]])*(MEMin[temp[5]]-MEMin[temp[0]]))-((MEMin[temp[6]]-MEMin[temp[1]])*(MEMin[temp[10]]-MEMin[temp[0]]));

        result_a = float(result_a_up) / float(result_a_down);
        result_b = float(result_b_up) / float(result_b_down);

        int isIn = (0 <= result_a && result_a <=1) && ((0 <= result_b && result_b <= 1)) && ((0 <= (result_a+result_b) && (result_a+result_b) <= 1));

        IMAGEin[(i*HEIGHTs+j)*CHANNELS] += (int)(float(MEMin[temp[2]]) + (float(MEMin[temp[7]])-float(MEMin[temp[2]]))*result_a + (float(MEMin[temp[12]])-float(MEMin[temp[2]]))*result_b) * isIn;      //Red Channel
        IMAGEin[(i*HEIGHTs+j)*CHANNELS+1] += (int)(float(MEMin[temp[3]]) + (float(MEMin[temp[8]])-float(MEMin[temp[3]]))*result_a + (float(MEMin[temp[13]])-float(MEMin[temp[3]]))*result_b) * isIn;    //Green Channel
        IMAGEin[(i*HEIGHTs+j)*CHANNELS+2] += (int)(float(MEMin[temp[4]]) + (float(MEMin[temp[9]])-float(MEMin[temp[4]]))*result_a + (float(MEMin[temp[14]])-float(MEMin[temp[4]]))*result_b) * isIn;    //Blue Channel

}

//The information each device
struct DataStruct {
    int                 deviceID;
    unsigned char       IMAGE_SEG[WIDTH*HEIGHTs*CHANNELS];
};

void* routine( void *pvoidData ) {
        DataStruct  *data = (DataStruct*)pvoidData;
        unsigned char *dev_IMAGE;
        int *dev_MEM;
        unsigned char *IMAGE_SEG = data->IMAGE_SEG;

        HANDLE_ERROR(cudaSetDevice(data->deviceID));

        //initialize array
        memset(IMAGE_SEG, 0, WIDTH*HEIGHTs*CHANNELS);

        printf("Device %d Starting..\n", data->deviceID);

        //Evaluate Time
        cudaEvent_t start, stop;
        cudaEventCreate( &start );
        cudaEventCreate( &stop );

        HANDLE_ERROR( cudaMalloc( (void **)&dev_MEM, sizeof(int)*35) );                                //Creating int array each Block
        HANDLE_ERROR( cudaMalloc( (void **)&dev_IMAGE, sizeof(unsigned char)*WIDTH*HEIGHTs*CHANNELS) ); //output array

        cudaMemcpy(dev_MEM, MEM, sizeof(int)*256, cudaMemcpyHostToDevice);
        cudaMemset(dev_IMAGE, 0, sizeof(unsigned char)*WIDTH*HEIGHTs*CHANNELS);

        dim3    grid(WIDTH/TILE_WIDTH, HEIGHTs/TILE_HEIGHT);            //blocks in a grid
        dim3    block(TILE_WIDTH, TILE_HEIGHT);                         //threads in a block

        cudaEventRecord(start, 0);

        PRINT_POLYGON<<<grid,block>>>( dev_IMAGE, dev_MEM, data->deviceID, 0, 1, 2);                    //Start the Kernel
        PRINT_POLYGON<<<grid,block>>>( dev_IMAGE, dev_MEM, data->deviceID, 0, 2, 3);                    //Start the Kernel
        PRINT_POLYGON<<<grid,block>>>( dev_IMAGE, dev_MEM, data->deviceID, 0, 3, 4);                    //Start the Kernel
        PRINT_POLYGON<<<grid,block>>>( dev_IMAGE, dev_MEM, data->deviceID, 0, 4, 5);                    //Start the Kernel
        PRINT_POLYGON<<<grid,block>>>( dev_IMAGE, dev_MEM, data->deviceID, 3, 2, 4);                    //Start the Kernel
        PRINT_POLYGON<<<grid,block>>>( dev_IMAGE, dev_MEM, data->deviceID, 2, 6, 4);                    //Start the Kernel

        cudaEventRecord(stop, 0);
        cudaEventSynchronize(stop);

        HANDLE_ERROR( cudaMemcpy( IMAGE_SEG, dev_IMAGE, sizeof(unsigned char)*WIDTH*HEIGHTs*CHANNELS, cudaMemcpyDeviceToHost ) );
        HANDLE_ERROR( cudaFree( dev_MEM ) );
        HANDLE_ERROR( cudaFree( dev_IMAGE ) );

        cudaEventElapsedTime( &elapsed_time_ms[data->deviceID], start, stop );          //Calculate elapsed time
        cudaEventDestroy(start);
        cudaEventDestroy(stop);

        printf("Algorithm Elapsed Time : %f ms(Device %d)\n", elapsed_time_ms[data->deviceID], data->deviceID);
        printf("Device %d Complete!\n", data->deviceID);

        return 0;
}

int main( void )
{       
        int i;
        CUTThread thread[7];

        printf("Program Start.\n");                     
        LOAD_VERTEX();

        DataStruct data[DEVICENUM];                     //define device info

        for(i = 0; i < DEVICENUM; i++){
                data[i].deviceID = i;
                thread[i] = start_thread(routine, &(data[i]));
        }

        for(i = 0; i < DEVICENUM; i++){
                end_thread(thread[i]);
        }

        cudaFreeHost(MEM);

    return 0;
}
void LOAD_顶点(){
MEM[0]=60;//y0
MEM[1]=50;//x0
MEM[2]=128;//r0
MEM[3]=0;//g0
MEM[4]=70;//b0
MEM[5]=260;
MEM[6]=50;
MEM[7]=135;
MEM[8]=70;
MEM[9]=0;
MEM[10]=260;
MEM[11]=250;
MEM[12]=0;
MEM[13]=200;
MEM[14]=55;
MEM[15]=60;
MEM[16]=250;
MEM[17]=55;
MEM[18]=182;
MEM[19]=100;
MEM[20]=30;
MEM[21]=330;
MEM[22]=72;
MEM[23]=12;
MEM[24]=25;
MEM[25]=30;
MEM[26]=130;
MEM[27]=80;
MEM[28]=255;
MEM[29]=15;
MEM[30]=230;
MEM[31]=330;
MEM[32]=56;
MEM[33]=186;
MEM[34]=201;
}
__全局无效打印多边形(无符号字符*IMAGEin,int*MEMin,int dev\u ID,int a,int b,int c)
{
int i=块IDX.x*平铺宽度+螺纹IDX.x;
int j=块IDX.y*瓷砖高度+螺纹IDX.y;
浮动结果_a、结果_b;
内部温度[15];
int k;
对于(k=0;k<5;k++){
温度[k]=a*5+k;
温度[k+5]=b*5+k;
温度[k+10]=c*5+k;
}
int result_a_up=((MEMin[temp[11]]-MEMin[temp[1]])*(i-MEMin[temp[0]])-((MEMin[temp[10]-MEMin[temp[0]])*(j-MEMin[temp[1]]);
int result_a_down=((MEMin[temp[11]]-MEMin[temp[1]])*(MEMin[temp[5]-MEMin[temp[0]])-((MEMin[temp[6]]-MEMin[temp[1]])*(MEMin[temp[10]-MEMin[temp[0]]);
int result_b_up=((MEMin[temp[6]]-MEMin[temp[1]])*(MEMin[temp[0]]-i))-((MEMin[temp[5]]-MEMin[temp[0]])*(MEMin[temp[1]-j));
int result_b__down=((MEMin[temp[11]]-MEMin[temp[1]])*(MEMin[temp[5]-MEMin[temp[0]])-((MEMin[temp[6]]-MEMin[temp[1]])*(MEMin[temp[10]-MEMin[temp[0]]);
结果a=浮动(结果a向上)/浮动(结果a向下);
结果b=浮动(结果向上)/浮动(结果向下);
int-isIn=(0设备ID,0,3,4);//启动内核
PRINT_POLYGON(dev_IMAGE,dev_MEM,data->deviceID,0,4,5);//启动内核
PRINT_POLYGON(dev_IMAGE,dev_MEM,data->deviceID,3,2,4);//启动内核
PRINT_POLYGON(dev_IMAGE,dev_MEM,data->deviceID,2,6,4);//启动内核
cudaEventRecord(停止,0);
CUDAEVENTS同步(停止);
句柄错误(cudaMemcpy(图像SEG,dev_图像,sizeof(无符号字符)*宽度*高度*通道,cudaMemcpyDeviceToHost));
处理错误(cudaFree(dev_MEM));
处理错误(cudaFree(dev_图像));
CudaEventeLassedTime(&运行时间_ms[data->deviceID],start,stop);//计算运行时间
cudaEventDestroy(启动);
cudaEventDestroy(停止);
printf(“算法运行时间:%f ms(设备%d)\n”,运行时间\u ms[数据->设备ID],数据->设备ID);
printf(“设备%d完成!\n”,数据->设备ID);
返回0;
}
内部主(空)
{       
int i;
切削螺纹[7];
printf(“程序启动。\n”);
加载顶点();
数据结构数据[DEVICENUM];//定义设备信息
对于(i=0;i
既然您复制了,我也将复制:

对于您的内核,您发现占用率较高时性能降低,这很容易用占用率较高时的缓存溢出来解释

本地阵列
temp[]
在完全占用时需要1536×15×4=92160字节的缓存,而在占用率为33%(对于较小的8×8块大小)时,每个SM只需要512×15×4=30720字节。使用更大的48kB缓存/SM设置,后者可以完全缓存,几乎完全消除
temp[]
的片外内存访问,但即使在默认的16kB缓存/SM设置中,缓存命中概率也要高得多

由于无论如何都不需要
temp[]
阵列,因此最快的选择(在两种占用情况下)是完全消除它。如果在初始化循环之前插入一个
#pragma unroll
,编译器可能已经能够实现这一点。否则,用一个小宏或内联函数替换所有使用的
temp[]
,甚至只是将结果替换到代码中(在本例中,我甚至会觉得更可读)。

您是否真的会问“为什么16x16机箱比8x8机箱运行得慢,而16x16机箱实现了100%的占用率?”