截至目前,就內核執行時間而言,我的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