GPU 上的图像计算和值返回
Image computation on GPU and value returning
我有一个 C# 项目,在该项目中我从相机中检索灰度图像并对图像数据进行一些计算。计算非常耗时,因为我需要多次遍历整个图像并且我在 CPU.
上完成所有操作
现在我想尝试在 GPU 上进行评估 运行ning,但我很难实现这一目标,因为我之前从未进行过任何 GPU 计算。
该软件应该能够 运行 在具有不同硬件的多台计算机上,所以 CUDA 对我来说不是一个解决方案,因为代码也应该 运行 在只有板载的笔记本电脑上图形。经过一些研究,我遇到了 Cloo (found it on this project),这似乎是一个相当合理的选择。
到目前为止,我在我的项目中集成了 Cloo,并尝试获取 this hello world 示例 运行ning。我猜是 运行ning,因为我没有得到任何异常,但我不知道在哪里可以看到打印输出。
对于我的计算,我需要将图像传递给 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 值并在第二个循环块开始之前将它们相加。
之后我想 return 值 a
和 b
到我的 C# 代码并在那里使用它们。
所以,总结我的问题:
- Cloo 是这项任务的推荐选择吗?
- 将图像数据(16 位,短数组)和尺寸(
img_width
、img_height
)传递给 GPU 的最佳方式是什么?
- 如何 return 来自 GPU 的值?据我所知,内核总是用作
kernel void...
- 实现循环的最佳方式是什么?
我希望我的问题很清楚,并且我提供了足够的信息来理解我的挣扎。任何帮助表示赞赏。提前致谢。
让我们对问题进行逆向工程。了解image[][], image_height, image_width, a, b
的"dependency-chain"的高效处理
Ad 4 ) 相同 for
循环的串联性能较差
给定定义的代码,可能只有一个循环,因此可以降低开销成本,并且最好同时最大化 cache-aligned 矢量化代码。
Cache-Naive re-formulation:
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)
将代码移动到拆分串联循环只会增加这些开销,并破坏 code-performance 调整中任何可能的 cache-friendly 技巧。
Ad 3 + 2 ) 内核 call-signature + CPU-side 方法允许这个
OpenCL 和 Cloo 记录了这些细节,因此除了记录的方法之外,这里不需要任何神奇的东西。
然而,每个这样的 host-side 到 device-side + device-side 到 host-side 传输都有延迟成本。鉴于您声称 16bit-1920x1200 image-data 将在一个循环中 re-processed ~ 10 次 ,这些延迟有可能不需要花费在每个这样的循环 pass-through.
最差的performance-killer是内核数学密度很浅。问题是,内核中确实没有太多要计算的,所以任何有效的 SIMD / GPU 并行技巧的机会确实很低。
从这个意义上讲,CPU-side smart-vectorised 代码会比 ( H2D + D2H )-overheads-far latency-hostile computationally-shallow GPU-kernel处理中。
广告 1) 给定上面的 2+3 和 4,1 可能很容易失去意义
作为原型并提供额外的 cache-friendly 矢量化技巧,in-ram + in-cache 矢量化代码将有机会击败所有 OpenCL 和 mixed-GPU/CPU 自动化 ad-hoc 内核编译生成的设备代码及其计算量。
我有一个 C# 项目,在该项目中我从相机中检索灰度图像并对图像数据进行一些计算。计算非常耗时,因为我需要多次遍历整个图像并且我在 CPU.
上完成所有操作现在我想尝试在 GPU 上进行评估 运行ning,但我很难实现这一目标,因为我之前从未进行过任何 GPU 计算。
该软件应该能够 运行 在具有不同硬件的多台计算机上,所以 CUDA 对我来说不是一个解决方案,因为代码也应该 运行 在只有板载的笔记本电脑上图形。经过一些研究,我遇到了 Cloo (found it on this project),这似乎是一个相当合理的选择。
到目前为止,我在我的项目中集成了 Cloo,并尝试获取 this hello world 示例 运行ning。我猜是 运行ning,因为我没有得到任何异常,但我不知道在哪里可以看到打印输出。
对于我的计算,我需要将图像传递给 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 值并在第二个循环块开始之前将它们相加。
之后我想 return 值 a
和 b
到我的 C# 代码并在那里使用它们。
所以,总结我的问题:
- Cloo 是这项任务的推荐选择吗?
- 将图像数据(16 位,短数组)和尺寸(
img_width
、img_height
)传递给 GPU 的最佳方式是什么? - 如何 return 来自 GPU 的值?据我所知,内核总是用作
kernel void...
- 实现循环的最佳方式是什么?
我希望我的问题很清楚,并且我提供了足够的信息来理解我的挣扎。任何帮助表示赞赏。提前致谢。
让我们对问题进行逆向工程。了解image[][], image_height, image_width, a, b
Ad 4 ) 相同 for
循环的串联性能较差
给定定义的代码,可能只有一个循环,因此可以降低开销成本,并且最好同时最大化 cache-aligned 矢量化代码。
Cache-Naive re-formulation:
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)
将代码移动到拆分串联循环只会增加这些开销,并破坏 code-performance 调整中任何可能的 cache-friendly 技巧。
Ad 3 + 2 ) 内核 call-signature + CPU-side 方法允许这个
OpenCL 和 Cloo 记录了这些细节,因此除了记录的方法之外,这里不需要任何神奇的东西。
然而,每个这样的 host-side 到 device-side + device-side 到 host-side 传输都有延迟成本。鉴于您声称 16bit-1920x1200 image-data 将在一个循环中 re-processed ~ 10 次 ,这些延迟有可能不需要花费在每个这样的循环 pass-through.
最差的performance-killer是内核数学密度很浅。问题是,内核中确实没有太多要计算的,所以任何有效的 SIMD / GPU 并行技巧的机会确实很低。
从这个意义上讲,CPU-side smart-vectorised 代码会比 ( H2D + D2H )-overheads-far latency-hostile computationally-shallow GPU-kernel处理中。
广告 1) 给定上面的 2+3 和 4,1 可能很容易失去意义
作为原型并提供额外的 cache-friendly 矢量化技巧,in-ram + in-cache 矢量化代码将有机会击败所有 OpenCL 和 mixed-GPU/CPU 自动化 ad-hoc 内核编译生成的设备代码及其计算量。