cuda - cuda fortran cufftPlanMany
问题描述
我在使用 cufftPlanMany 时遇到问题。创建计划并进行正向和反向 FFT 后,我无法取回原始数据。请在附件中找到代码的最低版本。
program test_cufft
use cudafor
use cufft
integer :: plan_r2c
integer :: plan_c2r
real,allocatable,dimension(:,:,:,:), device :: eta_d
complex,allocatable,dimension(:,:,:,:), device :: etak_d
nv = 4
nx = 256
ny = 512
nz = 512
nx21 = nx/2+1
allocate( eta_d(nv,nx,ny,nz) )
allocate( etak_d(nv,nx21,ny,nz) )
batch = nv;
rank = 3;
n = (/ nx, ny, nz /);
idist = nx*ny*nz;
odist = nx21*ny*nz;
inembed = (/ nx, ny, nz /);
onembed = (/ nx21, ny, nz /);
istride = 1;
ostride = 1;
istat = cufftPlanMany( plan_r2c, rank, n, inembed, istride, idist, &
onembed, ostride, odist, CUFFT_R2C, batch )
istat = cufftPlanMany( plan_c2r, rank, n, onembed, ostride, odist, &
inembed, istride, idist, CUFFT_C2R, batch )
! Initialize eta_d
istat = cufftExecR2C( plan_r2c, eta_d, etak_d )
istat = cufftExecC2R( plan_c2r, etak_d, eta_d )
eta_d = eta_d/idist
end program test_cufft
问题是在我进行了正向和反向 FFT 之后,我无法取回原始数据。请问,我做错了什么?数据的顺序应该是eta_d(batch,nx,ny,nz) or eta_d(nx,ny,nz,batch)
?
解决方案
我会说正确的顺序是(nz, ny, nx, batch)
但是将这些与您的数组索引和存储顺序相关联也很重要。
在 CUFFT术语中,对于 3D 变换 (*),nz
方向是变化最快的索引,典型用法 (stride=1) 是内存中的相邻数据,对应于变换中的相邻元素。
对于 R2C/C2R 变换类型,这个方向(我认为它是沿行的元素,即“z”索引是列索引)也是在复域中“减少”的多维变换的方向.
考虑到这一点,我会以这种方式重写您的代码:
$ cat t4.cuf
program test_cufft
use cudafor
use cufft
integer :: plan_r2c
integer :: plan_c2r
real,allocatable,dimension(:,:,:,:), managed :: eta_d
complex,allocatable,dimension(:,:,:,:), managed :: etak_d
integer :: n(3), inembed(3), onembed(3),rank,istride,idist,ostride,odist,batch
nv = 4
nx = 8
ny = 8
nz = 4
nz21 = nz/2+1
allocate( eta_d(nz,ny,nx,nv) )
allocate( etak_d(nz21,ny,nx,nv) )
batch = nv;
rank = 3;
n = (/ nx, ny, nz /);
idist = nx*ny*nz;
odist = nx*ny*nz21;
inembed = (/ nx, ny, nz /);
onembed = (/ nx, ny, nz21 /);
istride = 1;
ostride = 1;
istat = cufftPlanMany( plan_r2c, rank, n, inembed, istride, idist, onembed, ostride, odist, CUFFT_R2C, batch )
istat = cufftPlanMany( plan_c2r, rank, n, onembed, ostride, odist, inembed, istride, idist, CUFFT_C2R, batch )
! Initialize eta_d
eta_d(:,:,:,:) = 1.0
eta_d(1,1,1,2) = 2.0
istat = cufftExecR2C( plan_r2c, eta_d, etak_d )
istat = cudaDeviceSynchronize()
eta_d(:,:,:,:) = 0.0
istat = cufftExecC2R( plan_c2r, etak_d, eta_d )
istat = cudaDeviceSynchronize()
eta_d = eta_d/idist
print *,eta_d(1,1,1,1)
print *,eta_d(1,1,1,2)
end program test_cufft
$ nvfortran t4.cuf -lcufft
$ ./a.out
1.000000
2.000000
$
(NVIDIA HPC SDK 20.9,Tesla V100 GPU)
它似乎为我的简单测试用例提供了预期的结果。
(*) 对于 2D 变换,ny
维度变化最快,而对于 1D 变换,nx
维度(当然)变化最快。
CUFFT 手册的多维变换和高级数据布局部分也可能是有用的阅读材料。
推荐阅读
- powershell - 卷曲错误:无法处理参数,因为参数名称“u”不明确
- php - 在 Woocommerce 产品选项卡部分中为评分菜单项标题添加星级评分
- javascript - 相扑选择 - 如何使加载的列表框始终打开?
- java - Java:为什么 FileReader 方法 .read() 需要一个变量?
- jestjs - 松散匹配 jest.toHaveBeenCalledWith 中的一个值
- jsp - 自升级到 Java 8 以来 AppEngine 项目的 JSP 页面中的 UTF-8 编码
- c# - openxml 写入 excel 模板不能正确地通过单元格进行交互
- django - Django 美味派:用户看不到任何数据
- mysql - sql 转储是否已加密移动到 docker 容器`docker-entrypoint-initdb.d` 中?
- c# - 如何将变量“推送”到另一个脚本以执行操作?