Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python skcuda.fft与numpy.fft.rfft不一样吗?_Python_Numpy_Fft_Pycuda_Cufft - Fatal编程技术网

Python skcuda.fft与numpy.fft.rfft不一样吗?

Python skcuda.fft与numpy.fft.rfft不一样吗?,python,numpy,fft,pycuda,cufft,Python,Numpy,Fft,Pycuda,Cufft,我试着测试fft的输出和numpy fft的单元测试结果,我很快意识到当它失败时,这并不是因为我做错了什么,但skcuda实际上并没有给出相同的答案。我知道它们会有一点不同,但至少有一个数字与numpy产生的数字相差几个数量级,而且allclose和几乎相等的都会返回大量错误(对于rtol=1e-6,33%和25%,对于atol=1e-6,16%)。我做错了什么?我能修好这个吗 测试文件: import pycuda.autoinit from skcuda import fft from py

我试着测试fft的输出和numpy fft的单元测试结果,我很快意识到当它失败时,这并不是因为我做错了什么,但skcuda实际上并没有给出相同的答案。我知道它们会有一点不同,但至少有一个数字与numpy产生的数字相差几个数量级,而且
allclose
几乎相等的
都会返回大量错误(对于
rtol=1e-6
,33%和25%,对于
atol=1e-6
,16%)。我做错了什么?我能修好这个吗

测试文件:

import pycuda.autoinit
from skcuda import fft
from pycuda import gpuarray
import numpy as np

def test_skcuda():
    array_0 = np.array([[1, 2, 3, 4, 5, 4, 3, 2, 1, 0]], dtype=np.float32)
    array_1 = array_0 * 10
    time_domain_signal = np.array([array_0[0], array_1[0]], dtype=np.float32)
    fft_point_count = 10
    fft_plan = fft.Plan(fft_point_count, np.float32, np.complex64,
                        batch=2)
    fft_reserved = gpuarray.empty((2, fft_point_count // 2 + 1), dtype=np.complex64)
    fft.fft(gpuarray.to_gpu(time_domain_signal), fft_reserved, fft_plan)

    np.testing.assert_array_almost_equal(
        np.fft.rfft(time_domain_signal, fft_point_count), fft_reserved.get())

test_skcuda()
断言失败:

AssertionError: 
Arrays are not almost equal to 6 decimals

(mismatch 25.0%)
 x: array([[ 2.500000e+01+0.000000e+00j, -8.472136e+00-6.155367e+00j,
        -1.193490e-15+2.331468e-15j,  4.721360e-01-1.453085e+00j,
         2.664535e-15+0.000000e+00j,  1.000000e+00+0.000000e+00j],...
 y: array([[ 2.500000e+01+0.000000e+00j, -8.472136e+00-6.155367e+00j,
         8.940697e-08+5.960464e-08j,  4.721359e-01-1.453085e+00j,
         0.000000e+00+0.000000e+00j,  1.000000e+00+0.000000e+00j],...
打印输出:

#numpy
[[ 2.50000000e+01+0.00000000e+00j -8.47213595e+00-6.15536707e+00j
  -1.19348975e-15+2.33146835e-15j  4.72135955e-01-1.45308506e+00j
   2.66453526e-15+0.00000000e+00j  1.00000000e+00+0.00000000e+00j]
 [ 2.50000000e+02+0.00000000e+00j -8.47213595e+01-6.15536707e+01j
  -1.11022302e-14+2.39808173e-14j  4.72135955e+00-1.45308506e+01j
   3.55271368e-14+7.10542736e-15j  1.00000000e+01+0.00000000e+00j]]

#skcuda
[[ 2.5000000e+01+0.0000000e+00j -8.4721355e+00-6.1553669e+00j
   8.9406967e-08+5.9604645e-08j  4.7213593e-01-1.4530852e+00j
   0.0000000e+00+0.0000000e+00j  1.0000000e+00+0.0000000e+00j]
 [ 2.5000000e+02+0.0000000e+00j -8.4721359e+01-6.1553673e+01j
   1.4305115e-06-4.7683716e-07j  4.7213597e+00-1.4530851e+01j
   0.0000000e+00+1.9073486e-06j  1.0000000e+01+0.0000000e+00j]]

FFT的输出有一个相对于输入值大小的误差。每个输出元素都是通过组合所有输入元素来计算的,因此它们的大小决定了结果的精度

您正在同一阵列中计算两个1D FFT。它们各自具有不同的幅值输入,因此应具有不同的幅值公差

下面的快速代码演示了如何实现这一点。我不知道如何调整
numpy.testing
中的任何函数

将numpy导入为np
array_0=np.array([[1,2,3,4,5,4,3,2,1,0]],dtype=np.float32)
数组_1=数组_0*10
时域信号=np.array([array\u 0[0],array\u 1[0]],dtype=np.float32)
#numpy结果
a=np.数组([[2.50000000e+01+0.00000000e+00j,-8.47213595e+00-6.15536707e+00j,
-1.19348975e-15+2.33146835e-15j,4.72135955e-01-1.45308506e+00j,
2.66453526e-15+0.00000000e+00j,1.00000000e+00+0.00000000e+00j],
[2.50000000e+02+0.00000000e+00j,-8.47213595e+01-6.15536707e+01j,
-1.11022302e-14+2.39808173e-14j,4.72135955e+00-1.45308506e+01j,
3.55271368e-14+7.10542736e-15j,1.00000000e+01+0.00000000e+00j]]
#skcuda结果
b=np.数组([[2.5000000e+01+0.0000000e+00j,-8.4721355e+00-6.1553669e+00j,
8.9406967e-08+5.9604645e-08j,4.7213593e-01-1.4530852e+00j,
0.0000000e+00+0.0000000e+00j,1.0000000e+00+0.0000000e+00j],
[2.5000000e+02+0.0000000e+00j,-8.4721359e+01-6.1553673e+01j,
1.4305115e-06-4.7683716e-07j,4.7213597e+00-1.4530851e+01j,
0.0000000e+00+1.9073486e-06j,1.0000000e+01+0.0000000e+00j]]
#结果数组行相对于平均绝对输入值的容差
#1e-6因为我们使用的是单精度浮点数
tol=np.平均值(np.绝对值(时域信号),轴=1)*1e-6
#计算绝对差,并将其与我们的耐受性进行比较
差异=平均绝对值(a-b)
如果np.any(diff>tol[:,None]):
打印('错误!!!')

这看起来很像舍入错误,单精度浮点精度约为8位小数(双精度浮点精度约为16位)

代替使用
numpy.fft
的另一种方法是使用直接支持单精度浮点的方法,例如:

from scipy import fftpack

x = np.array([1, 2, 3, 4, 5, 4, 3, 2, 1, 0])

y = fftpack.fft(
    np.array([x, x * 10], dtype=np.float32)
)
print(y[:,:6])
输出:

[[ 2.5000000e+01+0.0000000e+00j -8.4721355e+00-6.1553669e+00j
   8.9406967e-08+5.9604645e-08j  4.7213593e-01-1.4530852e+00j
   0.0000000e+00+0.0000000e+00j  1.0000000e+00+0.0000000e+00j]
 [ 2.5000000e+02+0.0000000e+00j -8.4721359e+01-6.1553673e+01j
   1.1920929e-06+1.9073486e-06j  4.7213583e+00-1.4530851e+01j
   0.0000000e+00+1.9073486e-06j  1.0000000e+01+0.0000000e+00j]]
从FFT(给定接近1.0的满标度输入或输出)得到的e-8(浮点)和e-15(双精度)的微小结果值基本上等于零(加上数字舍入噪声)

零+噪音==零+噪音


因此,您的结果实际上可能是相同的。

@CrisLuengo我已经用
np.testing.assert\u allclose
完成了这项工作,这导致
rtol=1e-6
仍有33%的误差,我同意,有些误差在数值精度范围内,但特别是每行的第三个x轴元素,对于每个numpy数组而言,它们彼此之间有很大的差异,相隔几个数量级。@CrisLuengo我本想使用atol,而不是rtol,结果还是得到了%16.6的差异,我假设从第三列的值来看。@CrisLuengo Cuda将使用你告诉它的任何东西,但如果你看这里,我强制所有东西都是np.float32,所以是的,所有东西都使用32位浮点。@CrisLuengo好的,这是有意义的,但是,numpy是否有一个错误函数能够真正识别这一点?到目前为止,似乎所有近似相等的函数仍然会拒绝它,我不确定在什么情况下以及如何说“这些东西足够接近!”@CrisLuengo well使用32位浮点实数,并在FFT变换期间创建复数,但是complex64是实部和虚部的两个32位浮点。我没有意识到numpy fft在内部使用双精度,即使您使用单精度作为输入。numpy倾向于公开基本原理,而scipy有很多,numpy的非常简朴,而不是非常确定的“一+噪声”,这些值都在
np.finfo(np.float32).eps(或类似的双打)。单精度浮点数在1e+-30之后很长一段时间内都可以使用,而在1e+-300之后则可以使用双倍精度浮点数。