我需要使用一个整数(0-99)作为参数,使用相同的数据运行我的GPU内核(ALEA库)100次。我试图在内核中实现这个循环但是我得到了奇怪的结果。我不得不把循环从内核和GPULaunch函数中取出来:
var lp = new LaunchParam(GridDim, BlockDim);
for (int i= 0; i < 100; i++)
{
GPULaunch(TestKernel, lp, Data, i);
}
代码的CPU版本经过高度优化,可有效使用4个内核(%100)。根据合并的内存访问原则重新组织内存中的数据后,我可以拥有%92占用率和%96全局负载效率。但是,GPU版本仅比CPU版本快50%。我怀疑循环GPULaunch是否有效。
如下图所示,我在NVIDIA Visual Profilier中看不到重复的内存传输。一旦我将数据加载到GPU(图中没有看到但对我来说不重要),我会得到100个循环输出的短暂内存传输,如右端所示。所以我的问题是:
答案 0 :(得分:0)
我试图再次在内核中实现循环并且它有效。我不确定这次有什么不同。这是明显的代码(只是模板而不是工作代码):
public class GPUModule : ILGPUModule
{
public GPUModule (GPUModuleTarget target) : base(target)
{
}
[Kernel]
Public MyKernel(deviceptr<int> Data)
{
var start = blockIdx.x * blockDim.x + threadIdx.x;
int ind = threadIdx.x;
for (int i=0;i<100;i++)
{
//Kernel Code here
}
}
public void Dilimle_VerilerB(deviceptr<int> Data
{
...
var lp = new LaunchParam(GridDim, BlockDim);
GPULaunch(TestKernel, lp, Data, HOIndex);
...
}
}
内核的唯一补充是整数“i”上的循环。不幸的是,它导致寄存器/线程计数从26跳到42,导致占用率从%100下降到%50,这使执行时间从2.1秒略微增加到2.3秒。因此,如果维持%100占用率,将循环带入内核将提高性能,从而大大消除了GPULaunch开销。
围绕GPULaunch循环的%100占用率正在使用1024个线程/块。更改为内核循环后,我将其更改为128个线程/块。这将Ocuppancy增加到%62并导致执行时间为1.1秒。因此,作为结论,将这样的循环引入内核可以使GPU性能提高2倍。
所以问题是为什么内核的寄存器/线程数从26增加到42,并且向内核添加一个整数循环。如果寄存器数量大约为30,我认为占用率仍然接近%100。