OpenCL Sinus 实施

OpenCL Sinus Implementation

我正在寻找 OpenCL Sinus 实施。 嗯,我知道,OpenCL 实现是特定于硬件供应商的,因此 Nvidia OpenCL 实现可能看起来与 AMD 不同。但我想知道,出于速度原因,我是否需要实施自己的窦。 接受这个,sinnative_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,否则,你可以添加你的类似级数扩展的算法,以便所有设备以相同的方式计算但有更多错误。