Свертка БПФ на графическом процессоре с использованием Cupy

Я пытаюсь использовать Cupy для выполнения операции свертки БПФ на графическом процессоре.

Используя исходный код для scipy.signal.fftconvolve, я придумал следующую функцию на основе Numpy, которая прекрасно работает:

import numpy as np

def FFTConvolve(in1, in2):

    if in1.ndim == in2.ndim == 0:  # scalar inputs
        return in1 * in2
    elif not in1.ndim == in2.ndim:
        raise ValueError("Dimensions do not match.")
    elif in1.size == 0 or in2.size == 0:  # empty arrays
        return array([])

    s1 = np.asarray(in1.shape)
    s2 = np.asarray(in2.shape)

    shape = s1 + s2 - 1

    fsize = 2 ** np.ceil(np.log2(shape)).astype(int) 
    fslice = tuple([slice(0, int(sz)) for sz in shape])

    ret = np.fft.ifft(np.fft.fft(in1, fsize) * np.fft.fft(in2, fsize))[fslice].copy()

    return ret

Я наивно пишу программу для Cupy так:

import cupy as cp

def FFTConvolve(in1, in2):

     if in1.ndim == in2.ndim == 0:  # scalar inputs
          return in1 * in2
     elif not in1.ndim == in2.ndim:
          raise ValueError("Dimensions do not match.")
     elif in1.size == 0 or in2.size == 0:  # empty arrays
          return array([])

     in1 = cp.asarray(in1)
     in2 = cp.asarray(in2)

     s1 = cp.asarray(in1.shape)
     s2 = cp.asarray(in2.shape)

     shape = s1 + s2 - 1

     fsize = 2 ** cp.ceil(cp.log2(shape)).astype(int) 
     fslice = tuple([slice(0, int(sz)) for sz in shape])

     ret = cp.fft.ifftn(cp.fft.fftn(in1, fsize) * cp.fft.fftn(in2, fsize))[fslice].copy()

     return ret

Последний дает мне следующую ошибку в строке enter code here:

TypeError: 'cupy.core.core.ndarray' object cannot be interpreted as an integer

Документация для cupy.fft.ftt означает, что он принимает кортеж как диапазон, но по какой-то причине читает его как cupy.ndarray.

Может ли кто-нибудь указать мне правильное направление?


person Jack Rolph    schedule 06.01.2020    source источник
comment
Что вы имеете в виду под диапазоном? Если вы имеете в виду s, похоже, вы передаете cupy.ndarray как fsize.   -  person niboshi    schedule 06.01.2020
comment
Я исправил, как вы предложили.   -  person Jack Rolph    schedule 06.01.2020


Ответы (1)


Решением было использовать команду cp.asnumpy():

def FFTConvolve(in1, in2):

    if in1.ndim == in2.ndim == 0:  # scalar inputs
        return in1 * in2
    elif not in1.ndim == in2.ndim:
        raise ValueError("Dimensions do not match.")
    elif in1.size == 0 or in2.size == 0:  # empty arrays
        return array([])

    s1 = np.asarray(in1.shape)
    s2 = np.asarray(in2.shape)

    shape = s1 + s2 - 1

    fsize = 2 ** np.ceil(np.log2(shape)).astype(int) 
    fslice = tuple([slice(0, int(sz)) for sz in shape])

    ret = cp.fft.ifftn(cp.fft.fftn(in1, np.asarray(fsize)) * cp.fft.fftn(in2, np.asarray(fsize)))[fslice].copy()
    return ret
person Jack Rolph    schedule 06.01.2020
comment
Не могли бы вы уточнить, где cp.asnumpy() используется с этим кодом? Я не вижу, как он вызывается здесь, и выполнение кода как есть приводит к следующей ошибке: ValueError: non-scalar numpy.ndarray cannot be used for fill - person Gabriel Ibagon; 17.02.2020