嗨我创建了两个内核来做一个简单的匹配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一)。
任何帮助,将不胜感激
你从哪里来过我的生活:)所以基本上垂直的内核需要比水平的更多的内存调用来降低性能? –
是的,如果我对你的代码的分析是正确的,那么第二个内核访问模式就会有“空白”。检查您的调试器/分析器以确保。 –
这对我来说最有意义:)非常感谢,你真的帮助了:) –