截至目前,就内核执行时间而言,我的GPU比我的CPU慢。我想也许因为我正在测试一个小样本,由于较小的启动开销,CPU最终以更快的速度完成。但是,当我测试内核的数据几乎是样本大小的10倍时,CPU仍然以更快的速度完成,而GPU几乎落后了400毫秒。在GPU中优化opencl中的内核代码
运行与2.39MB文件 CPU:43.511ms GPU:65.219ms
运行与32.9MB文件 CPU:289.541ms GPU:605.400ms
我使用本地内存试过,但我我确信我错误地使用了它,并且遇到了两个问题。内核在1000-3000ms之间的任何地方完成(取决于我为localWorkSize设置的大小),还是运行状态代码-5,即CL_OUT_OF_RESOURCES。
这是一位SO成员帮助我的内核。
__kernel void lowpass(__global float *Array, __global float *coefficients, __global float *Output) {
int globalId = get_global_id(0);
float sum=0.0f;
for (int i=0; i< 65; i++)
{
float tmp=0;
if (globalId+i > 63)
{
tmp=Array[i+globalId-64]*coefficients[64-i];
}
sum += tmp;
}
Output[globalId]=sum;
}
这是我尝试使用本地内存。第一位将是主机代码的一个片段,以下部分是内核。
//Set the size of localMem
status |= clSetKernelArg(
kernel,
2,
1024, //I had num_items*(float) but it gave me a -5. Num items is the amount of elements in my array (around 1.2 million elements)
null);
printf("Kernel Arg output status: %i \n", status);
//set a localWorkSize
localWorkSize[0] = 64;
//execute the kernel with localWorkSize included
status = clEnqueueNDRangeKernel(
cmdQueue,
kernel,
1,
NULL,
globalWorkSize,
localWorkSize,
0,
NULL,
&someEvent);
//Here is what I did to the kernel***************************************
__kernel void lowpass(__global float *Array, __global float *coefficients, __global float *Output, __local float *localMem) {
int globalId = get_global_id(0);
int localId = get_local_id(0);
localMem[localId] = globalId[globalId];
float sum=0.0f;
for (int i=0; i< 65; i++)
{
float tmp=0;
if (globalId+i > 63)
{
tmp=localMem[i+localId-64]*coefficients[64-i];
}
sum += tmp;
}
Output[globalId]=sum;
}
参考链接我想设置局部变量时使用:用于查找kernelWorkGroupSize How do I use local memory in OpenCL?
链接(这就是为什么我在kernelArg 1024集): CL_OUT_OF_RESOURCES for 2 millions floats with 1GB VRAM?
我已经看到其他人在GPU比CPU慢的情况下也存在类似的问题,但是对于其中的许多人来说,他们使用clEnqueueKernel而不是clEnqueueNDRangeKernel。
继承人我刚才的问题,如果你需要对这个内核的详细信息: Best approach to FIFO implementation in a kernel OpenCL
发现GPU的藏汉一些优化技巧。 https://developer.amd.com/wordpress/media/2012/10/Optimizations-ImageConvolution1.pdf
已编辑的代码;错误仍然存在
__kernel void lowpass2(__global float *Array, __global float *coefficients, __global float *Output) {
int globalId = get_global_id(0);
float sum=0.0f;
float tmp=0.0f;
for (int i=64-globalId; i< 65; i++)
{
tmp = 0.0f;
tmp=Array[i]*coefficients[i];
sum += tmp;
}
Output[globalId]=sum;
}
我敢肯定你真的* *不希望在你的''''''''循环中的'if()'语句。一个智能编译器*可能能够将'if'从循环中提取出来,但是一个gpu-driver *可能*没有时间或者智能来有效地完成这个任务。 – EOF
你解决/执行什么问题/算法? – mfa
@EOF我将查看switch语句,作为if()的替代方法。 – VedhaR