【发布时间】:2015-09-23 13:30:58
【问题描述】:
问题:
在 Opencl 1.2 中,没有像
这样的内置函数long sum_int4_elements_into_long(int4 v);
我的尝试:
所以我使用下面的代码(预取的展开循环的内部部分)
// acc is long
int4 tmp=arr[i+7];
acc+=tmp.x+tmp.y+tmp.z+tmp.w;
tmp=arr[i+6];
acc+=tmp.x+tmp.y+tmp.z+tmp.w;
tmp=arr[i+5];
acc+=tmp.x+tmp.y+tmp.z+tmp.w;
tmp=arr[i+4];"
acc+=tmp.x+tmp.y+tmp.z+tmp.w;
tmp=arr[i+3];
acc+=tmp.x+tmp.y+tmp.z+tmp.w;
tmp=arr[i+2];
acc+=tmp.x+tmp.y+tmp.z+tmp.w;
tmp=arr[i+1];
acc+=tmp.x+tmp.y+tmp.z+tmp.w;
tmp=arr[i];
acc+=tmp.x+tmp.y+tmp.z+tmp.w;
将整数数组 (int4 arr) 的所有元素求和(减少)到单个长变量中,与串行代码相比,速度提升仅为 +%20 到 +%30。如果它可以启用 SSE 或 AVX,它会快得多。
也试过了:
使用纯整数累加器将求和运算速度提高了 3 倍,但整数溢出,所以我只能使用长变量。然后我尝试使用 long4 和 long2 变量作为
// acc is a long4, arr is an int4 array
acc+=convert_long4(arr[...])
// acc is a long2, arr is an int2 array
acc+=convert_long2(arr[...])
但它失败并锁定了计算机(检查了索引和限制,没有问题)所以在与 AMD CPU 的硬件指令映射下,longn to intn 一定有问题。
澄清:
必须有一些等效的 AMD 和 INTEL 的 SIMD(SSE 或 AVX)汇编指令用于
32 bit integers in a 128-bit SSE register
| | | |
acc+=tmp.x + tmp.y + tmp.z + tmp.w
^
|
64-bit register
但不知何故opencl没有映射到这个或者我没有打包C99 指令足够好,因此 cl 编译器无法使用 SSE/AVX 指令。
最接近的内置浮动版本是
acc=dot(v,(float4)(1,1,1,1));
但我需要一个整数版本,因为 fp 需要 Kahan 的求和校正,这需要额外的时间。
编辑:
我不确定 int+int+int+int 是否会有适当的 long 结果,或者只是将 int 溢出到 long 中。
Opencl 版本:1.2 在 CPU 上运行(Java ----> Jocl)
CPU:AMD fx-8150
操作系统:64 位 windows 10
驱动程序:amd 的最新驱动程序。
日期:23.09.2015
比较:
16M 32 位整数,FX8150 @ 3300MHz(使用 8 个内核中的 6 个)
java 1.8_25 上的串行代码平均需要 16.5 毫秒。
Java-1.8 的 IntStream 平均耗时 13.5 ms (X.reduce(0, Integer::sum))
本题中的并行代码平均需要 12.5 毫秒 (使用单个工作组)
本题的并行代码平均耗时 5.8 毫秒 (使用四个工作组)
并行但溢出的非长版本需要 5 毫秒。 (达到内存带宽)
mfa 的回答:
acc=dot(v,(double4)(1,1,1,1));
平均需要 13.5 毫秒,但浮动版本平均需要 12.2 毫秒。
我不确定浮点数是否可以始终保持其精度以将 1.0(甚至 0.0)添加到非常大的 fp 数。
【问题讨论】:
标签: integer sum opencl long-integer reduce