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

如何在OpenACC内核中转换Fortran的move_alloc内置函数?

在OpenACC GPU环境下迁移可分配数组的动态扩容逻辑

OpenACC设备端内核不支持直接调用move_alloc——这个内置函数是主机端的内存操作接口,无法在GPU上执行。要实现主机端那种高效的无拷贝扩容,需要通过主机端协调设备内存的关联与管理,具体步骤如下:

核心思路

主机端主导设备内存的分配、数据拷贝和关联转移,内核仅负责数据的填充与拷贝操作,避免不必要的主机-设备数据传输。

具体实现步骤

假设你已经有一个包含可分配数组的Fortran结构体,且该结构体的数组已通过OpenACC指令卸载到GPU:

type :: my_data
  integer, allocatable :: arr(:)
end type my_data

type(my_data) :: gpu_struct
  1. 在设备端创建新的临时数组
    在主机端用!$acc enter data create指令直接在GPU上分配指定大小的临时数组tmp,跳过主机端分配再拷贝的步骤:

    integer, allocatable :: tmp(:)
    integer, parameter :: new_size = 200  ! 目标扩容大小
    !$acc enter data create(tmp(new_size))
    
  2. 内核中完成数据迁移与补0
    启动OpenACC内核,将原数组的有效数据拷贝到tmp,并对新增区域补0:

    integer :: old_size, i
    old_size = size(gpu_struct%arr)
    
    ! 拷贝原有数据
    !$acc parallel loop present(gpu_struct%arr, tmp)
    do i = 1, min(old_size, new_size)
      tmp(i) = gpu_struct%arr(i)
    end do
    !$acc end parallel loop
    
    ! 对新增区域补0(如果新尺寸大于原尺寸)
    if (new_size > old_size) then
      !$acc parallel loop present(tmp)
      do i = old_size + 1, new_size
        tmp(i) = 0
      end do
      !$acc end parallel loop
    end if
    
  3. 主机端完成内存关联转移
    先在主机端用move_alloc完成主机数组的无拷贝替换,再通过OpenACC指令将设备端的tmp内存关联到结构体的数组上,同时清理旧的设备内存:

    ! 主机端替换数组,tmp会被自动释放(主机端)
    call move_alloc(tmp, gpu_struct%arr)
    
    ! 删除设备端原有的旧数组内存(确保无其他引用)
    !$acc exit data delete(gpu_struct%arr)
    
    ! 将设备端的tmp内存与新的gpu_struct%arr关联
    !$acc attach(gpu_struct%arr)
    

关键注意事项

  • 避免设备端内存操作:所有内存分配、释放、关联操作必须在主机端执行,内核仅处理数据计算/拷贝。
  • attach指令的作用:attach不会重新分配设备内存,而是将主机端的可分配数组与已存在的设备内存绑定,实现类似move_alloc的无拷贝转移效果。
  • 内存安全:执行exit data delete前,必须确保旧的设备数组没有被其他内核或数据结构引用,否则会导致内存访问错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 00:42:28