首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >cuda记录压力

cuda记录压力
EN

Stack Overflow用户
提问于 2010-11-17 07:51:48
回答 3查看 3.5K关注 0票数 2

我有一个核函数做了线性最小二乘拟合。结果是线程使用了太多的寄存器,因此占用率很低。这是内核,

代码语言:javascript
复制
__global__
void strainAxialKernel(
    float* d_dis,
    float* d_str
){
    int i = threadIdx.x;
    float a = 0;
    float c = 0;
    float e = 0;
    float f = 0;
    int shift = (int)((float)(i*NEIGHBOURS)/(float)WINDOW_PER_LINE);
    int j;
    __shared__ float dis[WINDOW_PER_LINE];
    __shared__ float str[WINDOW_PER_LINE];

    // fetch data from global memory
    dis[i] = d_dis[blockIdx.x*WINDOW_PER_LINE+i];
    __syncthreads();

    // least square fit
    for (j=-shift; j<NEIGHBOURS-shift; j++)                                     
    {                                                                           
        a += j;                                                                 
        c += j*j;                                                               
        e += dis[i+j];                                                          
        f += (float(j))*dis[i+j];                                               
    }                                                                       
    str[i] = AMP*(a*e-NEIGHBOURS*f)/(a*a-NEIGHBOURS*c)/(float)BLOCK_SPACING;    

    // compensate attenuation
    if (COMPEN_EXP>0 && COMPEN_BASE>0)                                          
    {                                                                           
        str[i]                                                                  
        = (float)(str[i]*pow((float)i/(float)COMPEN_BASE+1.0f,COMPEN_EXP));     
    }   

    // write back to global memory
    if (!SIGN_PRESERVE && str[i]<0)                                             
    {                                                                           
        d_str[blockIdx.x*WINDOW_PER_LINE+i] = -str[i];                          
    }                                                                           
    else                                                                        
    {                                                                           
        d_str[blockIdx.x*WINDOW_PER_LINE+i] = str[i];                           
    }
}

我有32x404个块,每个块有96个线程。在GTS 250上,SM应能够处理8个区块。然而,visual profiler显示我每个线程有11个寄存器,因此,占用率是0.625 (每个SM 5个块)。顺便说一句,每个块使用的共享内存是792B,所以寄存器是问题所在。这场演出不是世界末日。我只是好奇有没有什么办法可以绕过这个问题。谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-11-19 06:10:39

在快速但有限的寄存器/共享内存和缓慢但大的全局内存之间总是存在权衡。没有办法“绕过”这种权衡。如果通过使用全局内存来减少寄存器使用量,则应该会获得更高的占用率,但内存访问速度会更慢。

也就是说,这里有一些使用更少寄存器的想法:

  1. 可以预先计算移位并存储在常量内存中吗?然后每个线程只需要查找

  1. ,Do,a和c必须是浮点数,

  1. ,或者,a和c可以从循环中删除并计算一次吗?并因此被完全删除??

A是作为一个简单的算术序列计算的,所以减少它...(类似这样的内容)

代码语言:javascript
复制
a = ((NEIGHBORS-shift) - (-shift) + 1) * ((NEIGHBORS-shift) + (-shift)) / 2

代码语言:javascript
复制
a = (NEIGHBORS + 1) * ((NEIGHBORS - 2*shift)) / 2

因此,请执行类似以下操作(您可能可以进一步减少这些表达式):

代码语言:javascript
复制
str[i] = AMP*((NEIGHBORS + 1) * ((NEIGHBORS - 2*shift)) / 2*e-NEIGHBOURS*f)
str[i] /= ((NEIGHBORS + 1) * ((NEIGHBORS - 2*shift)) / 2*(NEIGHBORS + 1) * ((NEIGHBORS - 2*shift)) / 2-NEIGHBOURS*c)
str[i] /= (float)BLOCK_SPACING;
票数 2
EN

Stack Overflow用户

发布于 2010-11-19 07:03:10

入住率不是问题。

GTS 250中SM (计算能力1.1)可能能够在其寄存器中同时容纳8个块(8x96线程),但它只有8个执行单元,这意味着在任何给定的时刻,8x96 (或者,在您的例子中,5x96)线程中只有8个线程在前进。试图在超载的SM上压缩更多的块是没有价值的。

事实上,您可以尝试使用-maxrregcount选项来增加寄存器的数量,这可能会对性能产生积极的影响。

票数 2
EN

Stack Overflow用户

发布于 2012-04-24 01:26:17

您可以使用启动界限来指示编译器为每个多处理器的最大线程数和最小块数生成寄存器映射。这可以减少寄存器数量,以便您可以达到所需的占用率。

对于您的情况,Nvidia的入住率计算器显示的理论峰值入住率为63%,这似乎就是您正在实现的目标。正如您提到的,这是由于您的寄存器计数,但也是由于每个块的线程数量。将每个块的线程数增加到128,并将寄存器计数减少到10,会产生100%的理论峰值占用。

要控制内核的启动范围,请执行以下操作:

代码语言:javascript
复制
__global__ void
__launch_bounds__(128, 6)
MyKernel(...)
{
    ...
}

然后只需启动128个线程的块大小,并享受您的占用。编译器生成的内核应该使用10个或更少的寄存器。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4200230

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档