2014-10-01 31 views
3

我试图从一般的pyOpenCL和GPGPU开始。pyOpenCL获得与numpy相比的不同结果

对于下面的dot产品代码,我得到了GPU和CPU版本之间相当不同的结果。我究竟做错了什么?

对于浮点错误来说,约0.5%的差异似乎很大,以解决差异。数组大小(〜9e-8相对于数组大小10000)的差异似乎增加了。也许这是跨块合并结果的问题......?无论哪种方式,让我感到不安。

我不知道它的问题:我在MacBook Air上,英特尔(R)酷睿(TM)i7-4650U CPU @ 1.70GHz运行此,与英特尔高清显卡5000

谢谢提前。

import pyopencl as cl 
import numpy 

from pyopencl.reduction import ReductionKernel 
import pyopencl.clrandom as cl_rand 

ctx = cl.create_some_context() 
queue = cl.CommandQueue(ctx) 

dot = ReductionKernel(ctx,         \ 
         dtype_out = numpy.float32,   \ 
         neutral  = "0",     \ 
         map_expr = "x[i]*y[i]",   \ 
         reduce_expr = "a+b",     \ 
         arguments = "__global const float *x, __global const float *y" 
         ) 

x = cl_rand.rand(queue, 100000000, dtype = numpy.float32) 
y = cl_rand.rand(queue, 100000000, dtype = numpy.float32) 

x_dot_y  =  dot(x,y).get()  # GPU: array(25001304.0, dtype=float32) 
x_dot_y_cpu = numpy.dot(x.get(), y.get()) # CPU:  24875690.0 

print abs(x_dot_y_cpu - x_dot_y)/x_dot_y # 0.0050496689740063489 

回答

2

这两种方法之间的值降低的顺序可能会有很大的不同。在大型数据集中,浮点舍入中的小错误很快就会累加起来。也可能存在影响结果精确度的底层实现的其他细节。

我已经在自己的机器上运行你的示例代码,并得到最终结果(〜0.5%)的类似差异。作为一个数据点,您可以在原始Python中实现一个非常简单的点积,并查看OpenCL结果和Numpy的差异。

例如,您可以添加一些简单的像到您的示例:

x_dot_y_naive = sum(a*b for a,b in zip(x.get(), y.get())) 

这里的结果我得到我的机器上:

OPENCL: 25003466.000000 
NUMPY: 24878146.000000 (0.5012%) 
NAIVE: 25003465.601387 (0.0000%) 

正如你所看到的,幼稚的做法是比Numpy更接近OpenCL版本。对此的一种解释可能是Numpy的dot函数可能使用了融合乘加(FMA)操作,这将改变中间结果的舍入方式。如果没有任何编译器选项来说明,OpenCL应该完全符合IEE-754标准,而不是使用更快的FMA操作。

+0

谢谢@jprice!我接受这个答案。看起来像使用pyOpenCL/pyCuda为繁重的另一个原因! – rairan 2014-10-01 18:43:48

+0

仅供参考 - 我在MATLAB中运行了一个类似的测试,除了无法使用GPU实现,因为AFAIK是基于Cuda的,我的GPU不支持Cuda。这里是结果: – rairan 2014-10-01 19:15:15

+0

NAIVE:\t 1.4725e + 04 MATLAB:\t 1.4725e + 04(3.8913e-14 diff) – rairan 2014-10-01 19:15:55

相关问题