GPU 上的图像计算和值返回



我有一个 C# 项目,在这个项目中,我从相机中检索灰度图像并对图像数据进行一些计算。计算非常耗时,因为我需要多次遍历整个图像,而这一切都是在 CPU 上完成的。

现在我想尝试让评估在 GPU 上运行,但我很难做到这一点,因为我以前从未做过任何 GPU 计算。

该软件应该能够在具有不同硬件的多台计算机上运行,因此例如 CUDA 对我来说不是一个解决方案,因为代码也应该在只有板载显卡的笔记本电脑上运行。经过一番研究,我遇到了Cloo(在这个项目中找到了它),这似乎是一个相当合理的选择。

到目前为止,我将 Cloo 集成到我的项目中,并尝试运行这个 hello world 示例。我想它正在运行,因为我没有任何异常,但我不知道在哪里可以看到打印的输出。

对于我的计算,我需要将图像传递给 GPU,并且在计算过程中还需要 x-y 坐标。因此,在 C# 中,计算如下所示:

int a = 0;
for (int y = 0; y < img_height; y++){
for (int x = 0; x < img_width; x++){
a += image[x,y] * x * y;
}
}
int b = 0;
for (int y = 0; y < img_height; y++){
for (int x = 0; x < img_width; x++){
b += image[x,y] * (x-a) * y;
}
}

现在我想让这些计算在 GPU 上运行,我想并行y-loop,以便在每个任务中运行一个x-loop。然后,我可以获取所有生成的 a 值,并在第二个循环块开始之前将它们相加。

之后,我想将值ab返回到我的 C# 代码并在那里使用它们。

所以,总结一下我的问题:

  1. 克鲁是这项任务的推荐选择吗?
  2. 将图像数据(16位,短数组)和尺寸(img_widthimg_height)传递给GPU的最佳方法是什么?
  3. 如何从 GPU 返回值?据我所知,内核总是被用作kernel void...
  4. 实现循环的最佳方法是什么?

我希望我的问题很清楚,我提供了足够的信息来理解我的挣扎。任何帮助,不胜感激。提前谢谢。

让我们对问题进行逆向工程。了解image[][], image_height, image_width, a, b"依赖链"的有效处理


广告 4 ) 相同for环路的串联性能不佳

给定定义的代码,可能只有一个循环,从而降低开销成本,最好还可以最大化缓存对齐的矢量化代码。

缓存幼稚重新表述:

int a = 0;
int c = 1;
for (     int  y = 0; y < img_height; y++ ){
for ( int  x = 0; x < img_width;  x++ ){
int      intermediate = image[x,y] * y; // .SET   PROD(i[x,y],y) 
a += x * intermediate;                  // .REUSE 1st
c -=     intermediate;                  // .REUSE 2nd
}
}
int b = a * c; // was my fault upon being in a hurry leaving for weekend :o)

将代码移动到拆分串联循环中只会增加这些开销,并破坏代码性能调整中任何可能的缓存友好技巧。


Ad 3 + 2 ) 内核调用签名 + CPU 端方法允许这样做

OpenCL 和 Cloo 记录了这些细节,因此除了记录的方法之外,这里不需要任何神奇的东西。

但是,每个此类主机端到设备端 + 设备端到主机端的传输都存在相关的延迟成本。鉴于您声称 16 位-1920x1200 图像数据将在循环中重新处理~ 10 次,因此这些延迟可能不需要花费在每次此类循环直通上。

最糟糕的性能杀手是非常浅的内核数学密度。问题是,内核中确实没有太多要计算的内容,因此任何有效的 SIMD/GPU 并行技巧的机会确实很低。

从这个意义上说,CPU端的智能矢量化代码将比(H2D + D2H)开销远延迟的计算浅层GPU内核处理要好得多。


广告 1) 给定上述 2+3 和 4,1 可能很容易失去意义

作为原型并赋予额外的缓存友好矢量化技巧,内存内 + 缓存内矢量化代码将有机会击败所有 OpenCL 和混合 GPU/CPU 自动临时内核编译生成的设备代码及其计算工作。

相关内容

  • 没有找到相关文章

最新更新