【发布时间】:2016-05-22 08:35:50
【问题描述】:
明天我有一个关于 OpenCL 的测试。我们有一些示例测试,但没有解决方案。 给出的是这段代码:
void scalar_add(int n, double *a, double *b, double *result) {
for (int i=0; i<n; i++)
result[i] = a[i] + b[i];
}
第一个任务是编写一个 OpenCL 内核。所以我的解决方案:
__kernel void scalar_add(
__global double *a,
__global double *b,
__global double *result
) {
size_t i = get_global_id(0;)
result[i] = a[i] + b[i];
}
对于每个元素,我从 A 读取一次,从 B 读取一次,向 C 写入一次。我不知道如何使用私有或本地内存来提高速度。 下一个问题是关于如何通过一个简单的更改来提高速度(“Welche kleine Änderung könnte auf einer Standard-Grafikkarte zu einer deutlichen Leistungssteigerung führen?”)。 有没有办法提高速度?
内核只从 A 和 B 读取,所以也许可以使用它。我尝试对参数 A 和 B 使用“__local”,但这不会编译或运行。
【问题讨论】:
-
我唯一能想到的就是将计算批处理在一起,因为内核只是一个计算。因此,在一个内核中计算多个元素以提高一致性并减少调度内核时的开销。我不知道这是否算作“一个简单的改变”..
-
在许多 GPU 中,使用向量类型无济于事,但实际上会生成不能很好地合并的内存访问模式。同时这里的算术强度是如此之低,以至于内存带宽无论如何都会成为限制。这里最好的性能提示实际上是:不要使用 GPU,使用 CPU 上的 SIMD 指令进行标量加法。也许答案是用浮点数替换双精度?
-
@JanLucas wat
-
@Hubert:最大化传输中的数据量通常是个好主意,但在这里它不太可能有帮助。该内核将使用如此少的寄存器,无论如何您都将获得完美的占用,并且每个线程已经在运行中产生了 16(读取)+8(写入)字节。我们可以使用little's law来计算我们需要多少个飞行字节(例如K20):208 GB/s * 300 Cycles / (706 MCycle/s) = 88 kB in flight。 K20 上的完全占用是 13*2048 个线程,因此每个线程需要 3.3 个字节的运行时间 -> 我们使用所有内存带宽,因为每个线程有更多的 8 个字节在运行
-
使用浮点数会减少两倍所需的带宽,同时,浮点数的算术吞吐量远高于几乎所有 GPU 的两倍(至少两倍,但通常是 8x-32x)跨度>
标签: performance opencl