将 NumPy 数组转换为 cufftComplex

Posted

技术标签:

【中文标题】将 NumPy 数组转换为 cufftComplex【英文标题】:Converting a NumPy Array to cufftComplex 【发布时间】:2018-05-22 21:57:32 【问题描述】:

我正在编写一个脚本来使用基于 GPU/CUDA 的 cuFFT 库执行 FFT。 CuFFT 要求输入数据必须采用指定为“cufftComplex”的格式。但是我的输入数据是 numpy.complex64 格式。我正在使用 Python C-API 将数据从 python 发送到 C。如何在两种格式之间进行转换?目前我的代码如下所示:

#include<python2.7/Python.h>
#include<numpy/arrayobject.h>
#include<cufft.h>


void compute_BP(PyObject* inputData, pyObject* OutputData, int Nfft)

   cuffthandle plan;
   cuFFTPlan1d(&plan, Nfft, CUFFT_C2C, CUFFT_INVERSE);
   cuFFTExecC2C(plan, inputData, OutputData, CUFFT_INVERSE);
   ...
 

编译时出现以下错误:

错误:“PyObject *”类型的参数与“cufftComplex”类型的参数不兼容。

【问题讨论】:

cufft 不能从 __global__ 函数调用(没有 cufft 设备 API),所以我怀疑你的代码看起来像这样。如果它确实看起来像这样,那么无论您对数据格式有什么顾虑,它都不会起作用。 @RobertRovella:删除 global std::complex&lt;double&gt; 在 C++ 中的布局应该完全匹配 cufftDoubleComplex,而 std::complex&lt;float&gt; 在 C++ 中的布局应该完全匹配 cufftComplex。有了这些信息,您的问题实际上变成了如何将 python (numpy) 复杂类型转换为 C++,反之亦然。为此,this question 提供了一个合适的答案。 您在这里的代码/想法超出了已经指出的范围。您不能只是盲目地将任意 Python 对象指针转换为 C 数组指针,也不能将主机 C 数组指针传递给 cuFFT。您必须使用 Python buffer interface 来访问数组内存和适当的 CUDA API 来将该内存分配和复制到设备 【参考方案1】:

借用我的回答 here,这是一个工作示例,说明如何在 python 中使用 ctypes 在 python 脚本中运行 cufft 库中的函数,使用 numpy 数据:

$ cat mylib.cpp
#include <cufft.h>
#include <stdio.h>
#include <assert.h>
#include <cuda_runtime_api.h>
extern "C"
void fft(void *input, void *output, size_t N)

  cufftHandle plan;
  cufftComplex *d_in, *d_out;
  size_t ds = N*sizeof(cufftComplex);
  cudaMalloc((void **)&d_in,  ds);
  cudaMalloc((void **)&d_out, ds);
  cufftResult res = cufftPlan1d(&plan, N, CUFFT_C2C, 1);
  assert(res == CUFFT_SUCCESS);
  cudaMemcpy(d_in, input, ds, cudaMemcpyHostToDevice);
  res = cufftExecC2C(plan, d_in, d_out, CUFFT_FORWARD);
  assert(res == CUFFT_SUCCESS);
  cudaMemcpy(output, d_out, ds, cudaMemcpyDeviceToHost);
  printf("%s\n", cudaGetErrorString(cudaGetLastError()));
  printf("from shared object:\n");
  for (int i = 0; i < N; i++)
    printf("%.1f + j%.1f, ", ((cufftComplex *)output)[i].x, ((cufftComplex *)output)[i].y);
  printf("\n");


$ cat t8.py
import ctypes
import os
import sys
import numpy as np

mylib = ctypes.cdll.LoadLibrary('libmylib.so')

N = 4
mydata = np.ones((N), dtype = np.complex64)
myresult = np.zeros((N), dtype = np.complex64)
mylib.fft(ctypes.c_void_p(mydata.ctypes.data), ctypes.c_void_p(myresult.ctypes.data), ctypes.c_size_t(N))
print(myresult)

$ g++ -fPIC -I/usr/local/cuda/include --shared mylib.cpp -L/usr/local/cuda/lib64 -lcufft -lcudart -o libmylib.so
$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd` python t8.py
no error
from shared object:
4.0 + j0.0, 0.0 + j0.0, 0.0 + j0.0, 0.0 + j0.0,
[4.+0.j 0.+0.j 0.+0.j 0.+0.j]
$

【讨论】:

这通过在 numpy 数组中使用烘焙的 ctypes 接口来回避使用缓冲区接口的整个需要,这是非常常见的方法

以上是关于将 NumPy 数组转换为 cufftComplex的主要内容,如果未能解决你的问题,请参考以下文章

将两个numpy数组转换为数据框

如何将numpy数组列表转换为numpy数组

将字符串转换为numpy数组

如何将 2D float numpy 数组转换为 2D int numpy 数组?

将numpy数组转换为rgb图像

有没有办法将 numpy 数组转换为数据框,然后再转换回 numpy 数组并仍保持原始形状?