OpenCL Sinus 实施
OpenCL Sinus Implementation
我正在寻找 OpenCL Sinus 实施。
嗯,我知道,OpenCL 实现是特定于硬件供应商的,因此 Nvidia OpenCL 实现可能看起来与 AMD 不同。但我想知道,出于速度原因,我是否需要实施自己的窦。
接受这个,sin
和native_sin
的区别在哪里?
这是一个 amd 实现,在其自身上测试重复的 sin 函数,因此随着迭代次数的增加(本例中为 100),任何错误都会使其更加混乱:
__kernel void sin_test_0(__global float *a)
{
int id = get_global_id(0);
float r=a[id];
for(int i=0;i<100;i++)
r = sin(r);
a[id]=r;
}
a[id] 为所有 16m 元素首先赋予值 1111。
- sin() = -0,1692203;在 265 毫秒(320 核 gpu)和 1950 毫秒(8 核 cpu 使用 float4)中完成
- C# 的数学库实现 = -0,1692202;在 55505 毫秒(单核)和 12998 毫秒(4 线程)和 8200 毫秒(最大线程 Parallel.For)内完成,没有任何关于矢量化的明确编译器提示。
- native_sin() = -0,1692208; 45 毫秒内完成
- half_sin() = -0,1692207;在 165 毫秒内完成
- 正弦级数展开(对于输入=[-1,1])= -0,155202; 40 毫秒内完成
只有第7位数字不同,这可能是因为C#使用double类型进行计算,原生版本比原来的要远一些。一半似乎比原生更好但更慢。 Half_sin 的范围是 -2^16 到 2^16。
系列扩展:
float sin_se(float x)
{
x -= 6.28318530718f*(convert_int(x*0.15915494309f));
float xs=x*x;
float xc=x*x*x;
return ((x - xc*0.166666f) + (xc*xs)*0.0083333f)- (xc*xs*xs)*0.0001984f;
}
如果输入介于 -1 和 +1 之间,则不需要第一行,这样会更快。
native_sin() 可能正在使用其基于硬件的选项来加速。这些选项可以是查找 table 的幻数和 newton-raphson 引擎。您不得通过软件仿真超过这些部件的性能以获得相同的错误。上面的例子是在 gpu 上,使用 cpu 有细微差别。即使 opencl 规定所有设备的 ULP 误差必须小于 100,一个设备可能有 90 ULP,但其他 70ULP 和累积误差会增加它们之间的差距。如果你认为你不会累积太多错误并且如果你有安全数字,那么你可以只使用 native_sin,否则,你可以添加你的类似级数扩展的算法,以便所有设备以相同的方式计算但有更多错误。
我正在寻找 OpenCL Sinus 实施。
嗯,我知道,OpenCL 实现是特定于硬件供应商的,因此 Nvidia OpenCL 实现可能看起来与 AMD 不同。但我想知道,出于速度原因,我是否需要实施自己的窦。
接受这个,sin
和native_sin
的区别在哪里?
这是一个 amd 实现,在其自身上测试重复的 sin 函数,因此随着迭代次数的增加(本例中为 100),任何错误都会使其更加混乱:
__kernel void sin_test_0(__global float *a)
{
int id = get_global_id(0);
float r=a[id];
for(int i=0;i<100;i++)
r = sin(r);
a[id]=r;
}
a[id] 为所有 16m 元素首先赋予值 1111。
- sin() = -0,1692203;在 265 毫秒(320 核 gpu)和 1950 毫秒(8 核 cpu 使用 float4)中完成
- C# 的数学库实现 = -0,1692202;在 55505 毫秒(单核)和 12998 毫秒(4 线程)和 8200 毫秒(最大线程 Parallel.For)内完成,没有任何关于矢量化的明确编译器提示。
- native_sin() = -0,1692208; 45 毫秒内完成
- half_sin() = -0,1692207;在 165 毫秒内完成
- 正弦级数展开(对于输入=[-1,1])= -0,155202; 40 毫秒内完成
只有第7位数字不同,这可能是因为C#使用double类型进行计算,原生版本比原来的要远一些。一半似乎比原生更好但更慢。 Half_sin 的范围是 -2^16 到 2^16。
系列扩展:
float sin_se(float x)
{
x -= 6.28318530718f*(convert_int(x*0.15915494309f));
float xs=x*x;
float xc=x*x*x;
return ((x - xc*0.166666f) + (xc*xs)*0.0083333f)- (xc*xs*xs)*0.0001984f;
}
如果输入介于 -1 和 +1 之间,则不需要第一行,这样会更快。
native_sin() 可能正在使用其基于硬件的选项来加速。这些选项可以是查找 table 的幻数和 newton-raphson 引擎。您不得通过软件仿真超过这些部件的性能以获得相同的错误。上面的例子是在 gpu 上,使用 cpu 有细微差别。即使 opencl 规定所有设备的 ULP 误差必须小于 100,一个设备可能有 90 ULP,但其他 70ULP 和累积误差会增加它们之间的差距。如果你认为你不会累积太多错误并且如果你有安全数字,那么你可以只使用 native_sin,否则,你可以添加你的类似级数扩展的算法,以便所有设备以相同的方式计算但有更多错误。