嗨我創建了兩個內核來做一個簡單的匹配deshredder程序與OpenCL和定時運行。這兩個內核做他們應該做的事情,但是由於我無法破譯的原因,其中一個運行速度比另一個慢得多:/唯一真正的區別是我如何存儲發送的數據以及匹配是如何發生的。OpenCL核心問題
__kernel void Horizontal_Match_Orig(
__global int* allShreds,
__global int* matchOut,
const unsigned int shredCount,
const unsigned int pixelCount)
{
int match = 0;
int GlobalID = get_global_id(0);
int currShred = GlobalID/pixelCount;
int thisPixel = GlobalID - (currShred * pixelCount);
int matchPixel = allShreds[GlobalID];//currShred*pixelCount+thisPixel];
for (int i = 0; i < shredCount; i++)
{
match = 0;
if (matchPixel == allShreds[(i * pixelCount) + thisPixel])
{
if (matchPixel == 0)
{
match = match + 150;
}
else match = match + 1;
}
else match = match - 50;
atomic_add(&matchOut[(currShred * shredCount) + i], match);
}
}
此內核水平得到切絲邊緣,所以一個切絲的像素佔用POS 0到n在陣列allShreds再下切絲的像素被從POS n + 1個存儲到M(其中n =像素數量,m =增加的像素數量)。 GPU的每個線程都有一個像素與合作,並與它匹配反對所有其他Shred的對應像素(包括自身)
__kernel void Vertical(
__global int* allShreds,
__global int* matchOut,
const int numShreds,
const int pixelsPerEdge)
{
int GlobalID = get_global_id(0);
int myMatch = allShreds[GlobalID];
int myShred = GlobalID % numShreds;
int thisRow = GlobalID/numShreds;
for (int matchShred = 0; matchShred < numShreds; matchShred++)
{
int match = 0;
int matchPixel = allShreds[(thisRow * numShreds) + matchShred];
if (myMatch == matchPixel)
{
if (myMatch == 0)
match = 150;
else
match = 1;
}
else match = -50;
atomic_add(&matchOut[(myShred * numShreds) + matchShred], match);
}
}
這個內核垂直得到一絲一毫的邊緣,因此,所有的碎片的第一像素被存儲在pos 0到n中,則所有碎片的第二個像素被存儲在pos n + 1 ot m(其中n =碎片的數量,並且m =被添加到n的碎片的數量)。該過程類似於前一個過程,每個線程獲取一個像素並將其與其他每個細絲的相應像素進行匹配。
兩者都給出了相同的結果針對純序列程序測試的正確結果。從理論上講,它們應該運行在大致相同的時間內,垂直運行的可能性會更快,因爲原子添加對它的影響不應該太大......但是運行速度會更慢......任何想法?
這是我使用啓動它的代碼(我使用它爲C#包裝):
theContext.EnqueueNDRangeKernel(1, null, new int[] { minRows * shredcount }, null, out clEvent);
與全球總工作量等於像素中的每個的總數量(#Shreds X #Pixels一)。
任何幫助,將不勝感激
你從哪裏來過我的生活:)所以基本上垂直的內核需要比水平的更多的內存調用來降低性能? –
是的,如果我對你的代碼的分析是正確的,那麼第二個內核訪問模式就會有「空白」。檢查您的調試器/分析器以確保。 –
這對我來說最有意義:)非常感謝,你真的幫助了:) –