You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用acc_set_cuda_stream?CUDA与OpenACC流同步问题排查

问题:OpenACC流与CUDA流绑定的语法错误及解决

背景

我通过以下方式创建CUDA流,并将其绑定到cuFFT计划:

创建CUDA流

integer(kind=cuda_stream_kind) :: stream1
istat = cudaStreamCreate(stream1)

绑定到cuFFT计划

err_dir = err_dir + cufftPlan2D(plan_dir1,NY,NY,CUFFT_D2Z)
err_dir = err_dir + cufftSetStream(plan_dir1,stream1)

cuFFT执行及后续OpenACC循环

在执行cuFFT的子程序中,传入plan_dir1的代码如下:

subroutine new_fft_dir(z,plan)

  !$acc host_data use_device(z)
  ierr = ierr + cufftExecD2Z(plan,z,z)
  !$acc end host_data

  !$acc parallel loop collapse(2) present(z)
  do i=1,NXP2
  do j=1,NY
  z(i,j) = z(i,j)/NY**2
  enddo
  enddo
  !$acc end parallel loop

问题重现

我尝试将OpenACC流与CUDA流stream1绑定,使用以下代码时触发语法错误:

integer(kind=cuda_stream_kind) :: stream1
istat = cudaStreamCreate(stream1)
integer :: stream
istat = cudaStreamCreate(stream1)
acc_set_cuda_stream(stream,stream1)

错误提示:

NVFORTRAN-S-0034-Syntax error at or near end of line (main.f90: 48)

我的目标是给后续OpenACC循环添加async子句,让它和FFT在同一个CUDA流中执行:

!$acc parallel loop collapse(2) present(z) async(stream)
  do i=1,NXP2
  do j=1,NY
  z(i,j) = z(i,j)/NY**2
  enddo
  enddo
  !$acc end parallel loop

请问问题是否出在使用integer(kind=cuda_stream_kind)而非cudaStream_t stream?


问题分析与解决

1. 语法错误的直接原因

你重复调用cudaStreamCreate(stream1)属于冗余代码,但并非语法错误根源。真正的问题是**acc_set_cuda_stream的参数类型与使用方式不匹配**:

  • OpenACC的acc_set_cuda_stream第一个参数需要的是OpenACC异步队列的整数标识符(需通过acc_create_stream创建并返回),而你直接声明了普通integer :: stream却未初始化。
  • 第二个参数是CUDA流句柄,用integer(kind=cuda_stream_kind)声明是正确的,它和cudaStream_t在Fortran中等价(cudaStream_t本质是指针类型,Fortran中用对应kind的整数存储)。

2. 正确的绑定流程

要让OpenACC循环与cuFFT在同一CUDA流执行,正确步骤如下:

步骤1:创建CUDA流

integer(kind=cuda_stream_kind) :: stream1
istat = cudaStreamCreate(stream1)

步骤2:创建OpenACC异步队列并绑定到CUDA流

integer :: acc_stream_id
! 创建OpenACC异步队列
istat = acc_create_stream(acc_stream_id)
! 将队列绑定到已有的CUDA流stream1
istat = acc_set_cuda_stream(acc_stream_id, stream1)

步骤3:在OpenACC循环中使用该异步队列

!$acc parallel loop collapse(2) present(z) async(acc_stream_id)
do i=1,NXP2
do j=1,NY
z(i,j) = z(i,j)/NY**2
enddo
enddo
!$acc end parallel loop

3. 额外注意事项

  • 你已经通过cufftSetStream将plan_dir1绑定到stream1,这部分是正确的,确保了cuFFT执行在目标流中。
  • 若需要同步流,可使用cudaStreamSynchronize(stream1)或acc_wait(acc_stream_id)。

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 22:42:24