使用并行 NetCDF 保存分布式 3D 复杂数组

2024-01-07

我有一个用 Fortran 编写的基于 MPI 的程序,它在每个节点(2D 时间序列的部分)生成复杂数据的 3D 数组。我想使用并行 I/O 将这些数组写入单个文件,该文件可以相对轻松地在 python 中打开以进行进一步分析/可视化。理想情况下,我希望解决方案具有内存效率(即避免创建中间临时数组)。

使用 NetCDF,我成功地适应了子程序 https://www.archer.ac.uk/documentation/white-papers/fortanIO_netCDF/fortranIO_netCDF.pdf它针对 3D 实数数组实现了这一点。然而,当涉及到复杂数组时,我遇到了障碍。

在下面的代码中,我尝试通过创建由两个实数组成的复合数据类型,并假设 Fortran 复数数据类型的实部和虚部连续存储在 3D 数组的第一维中,将子例程从实数扩展到复数。

 module IO

    use NetCDF
    use, intrinsic :: iso_fortran_env, only: dp => real64

    implicit none

    contains

        subroutine output_3D(dataname, starts, ends, global_data_dims, &
            local_data, MPI_communicator)

        character(len=*), intent(in) :: dataname
        integer, dimension(3), intent(in) :: starts
        integer, dimension(3), intent(in) :: ends
        integer, dimension(3), intent(in) :: global_data_dims

        complex(dp), intent(in) :: local_data(   1:(ends(1) - starts(1)+ 1), &
                                                1:(ends(2) - starts(2) + 1), &
                                                1:(ends(3) - starts(3) + 1))

        integer, dimension(3) :: expanded_starts

        integer, intent(in) :: MPI_communicator

        integer :: ncid, varid, dimid(3)
        integer :: counts(3)

        integer :: typeid

        expanded_starts(1) = (starts(1))* 2 + 1
        expanded_starts = starts(2) 
        expanded_starts(3) = starts(3)

        call check(nf90_create( trim(dataname)//'.cdf', &
                                IOR(NF90_NETCDF4, NF90_MPIIO), &
                                ncid, &
                                comm = MPI_communicator, &
                                info = MPI_INFO_NULL))

        call check(nf90_def_dim(ncid, "x", global_data_dims(1), dimid(1)))
        call check(nf90_def_dim(ncid, "y", global_data_dims(2) * 2, dimid(2)))
        call check(nf90_def_dim(ncid, "z", global_data_dims(3), dimid(3)))

        ! define a complex data type consisting of two real(8)
        call check(nf90_def_compound(ncid, 16, "COMPLEX", typeid))
        call check(nf90_insert_compound(ncid, typeid, "REAL", 0, NF90_DOUBLE))
        call check(nf90_insert_compound(ncid, typeid, "IMAG", 8, NF90_DOUBLE))

        ! define a 3D variable of type "complex"
        call check(nf90_def_var(ncid, dataname, typeid, dimid, varid))

        ! exit define mode
        call check(nf90_enddef(ncid))

        ! Now in NETCDF data mode

        ! set to use MPI/PnetCDF collective I/O
        call check(nf90_var_par_access(ncid, varid, NF90_COLLECTIVE))

        counts(1) = (ends(1) - starts(1) + 1) * 2
        counts(2) = (ends(2) - starts(2) + 1)
        counts(3) = (ends(3) - starts(3) + 1)

        call check(nf90_put_var(ncid, &
                                varid, &
                                local_data, &
                                start = expanded_starts,&
                                count = counts))

        ! close the file
        call check(nf90_close(ncid))

        return

    end subroutine output_3D

    subroutine check(status)

        integer, intent ( in) :: status

        if(status /= nf90_noerr) then
            print *, trim(nf90_strerror(status))
            stop 2
        end if

    end subroutine check

end module IO

program test_write

    use IO
    use MPI

    complex(dp) :: data(2,2,3)

    integer :: flock
    integer :: rank
    integer :: ierr

    integer :: i, j, k

    call MPI_init(ierr)
    call MPI_comm_size(MPI_comm_world, flock, ierr)
    call MPI_comm_rank(MPI_comm_world, rank, ierr)

    do k = 1, 3
        do j = 1, 2
            do i = 1, 2
                data(i,j,k) = cmplx(i, j, 8)
            enddo
        enddo
    enddo

    if (rank == 0) then

        call output_3D_hdf5('out', [1,1,1], [2,2,3], [2,2,6], &
                data, MPI_comm_world)

    else

        call output_3D_hdf5('out', [1,1,4], [2,2,6], [2,2,6],  &
                data, MPI_comm_world)

    endif

    call MPI_finalize(ierr)

end program test_write

上述代码会导致编译时出现“There is no certain function for nf90_put_var”错误。这表明该函数对输入数组的数据类型不满意,因此显然我在复合数据类型的使用方面缺少一些东西。

编辑:一种简单的解决方法是将复杂数组分配给真实指针,如中所述this https://stackoverflow.com/questions/54817724/how-to-assign-pointers-to-a-complex-3d-array-in-fortran邮政。然后可以使用 numpy 对该数组进行重塑/重新转换,以得到 python 中的复杂数组。它有点笨重,而且有些令人不满意——但对于我现在的目的来说可能已经足够了。


这只是部分答案,原因您将在下面看到 - 但对于评论来说太长了。希望我能够找到丢失的信息并“升级”它,但这就是我到目前为止所拥有的。

如果您查看“复合类型介绍”下的 NetCDF4 文档,网址为https://www.unidata.ucar.edu/software/netcdf/fortran/docs/f90-user-define-data-types.html#f90-compound-types-introduction https://www.unidata.ucar.edu/software/netcdf/fortran/docs/f90-user-defined-data-types.html#f90-compound-types-introduction你会看见:

要以复合类型写入数据,首先使用nf90_def_compound要创建类型,请多次调用nf90_insert_compound添加到复合类型,然后用适当的方式写入数据nf90_put_var1, nf90_put_vara, nf90_put_vars, or nf90_put_varm call.

注意它没有提到nf90_put_var根本没有,但是有4个不同的功能。这有一定的道理,nf90_put_var大概可以很好地重载来处理 NetCDF 支持的所有内在类型(而且它完全是废话,它不支持复杂),因此对于非内在类型,大概有一些类似 C 的接口,类似于void *,我猜上面提到的四个函数就是这个实现的。

到目前为止一切顺利,您应该致电其中之一nf90_put_var1, nf90_put_vara, nf90_put_vars, or nf90_put_varm而不是nf90_put_var。现在是坏消息 - 我找不到这 4 个函数的任何文档。等效的 C 函数位于https://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html https://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html所以你也许能够从那里找出需要什么,但这不是很好 - 我至少会向 Unidata 提交一份错误报告,但这对我来说缺乏对复杂性的内在支持足以使我在别处寻找我的 I/O 解决方案...

当我在这里时,您确实不应该使用显式数字来表示变量的类型,我可以向您展示编译器在哪里complex(8)将无法编译。而是使用Selected_real_kind或类似的,或者使用内部模块 iso_fortran_env 中的常量,或者可能使用 iso_c_binding 中的常量,并且复数的类型与组成它的实数的类型相同。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用并行 NetCDF 保存分布式 3D 复杂数组 的相关文章

随机推荐

  • numpy 中两个浮点数之间以对数间隔的数字

    我正在尝试使用 python 获取两个浮点数之间对数间隔的 1000 个数字 例如 0 674 到 100 0 之间 这样做的目的是获得更多接近 0 674 的数字 而不仅仅是接近 100 的几个大数字 我尝试使用 numpy logspa
  • Python3'无法导入名称'cached_property'

    我无法让它发挥作用 我不断添加模块 但每次都找不到新模块 为什么这段代码在Python3 6中不起作用 Code from robobrowser import robobrowser from bs4 import BeautifulSo
  • 区分 Javascript 中的触摸和交换事件

    我有一个用于交换图像的图片库 在画廊中 我使用了 touchstart touchmove touchend 和 touchcancel 事件 但现在我还需要处理触摸事件 那么 我应该在移动设备上分别区分触摸和交换事件吗 我正在使用这个技巧
  • python `str()` 函数是否调用类的 `__str__()` 函数?

    如果我定义一个有自己的类 str 函数 是str a 相当于a str where a是我班级的一个实例吗 我检查了蟒蛇文档 https docs python org 2 library functions html str 它没有明确说
  • 在 Groovy 中使用字符串访问地图的地图元素

    鉴于我有一张这样的地图 def myMap b c X 还有一根绳子 def key b c 我想查看使用密钥获取值 X 的选项 我自己想出了两种方法来实现这一目标 但我对这些解决方案不太满意 1 Eval me theMap myMap
  • 加密:在javascript和python中模拟SSL

    由于中国防火墙阻止了 google appengine 的 https 端口 所以我想通过javascript和python模拟一个安全套接字层来保护我的用户信息不会被那些ISP和GFW捕获 我的计划 握手 浏览器请求服务器 服务器生成加密
  • jaxb 当 xsi:nil=true 如果任何子元素存在它仍然显示

    我有以下 xml 输出 当父元素具有属性 xsi nil true 即使子元素为 nillable true 时 我们如何隐藏子元素 endDate XML输出
  • REST API 中错误 HTTP 方法的返回代码?

    我们的API用户可以获得root发送文件 收集清单 GET请求根 API 地址 如果他发送POST 我们应该返回一些东西 同样的问题也适用于其他资源路径 例如发送PATCH在查询路径等上 并非所有方法在某些路径上都有意义 正如我从 HTTP
  • 使用插值在模板中渲染 html 字符串?

    使用角度 4 3 0 假设我有一个像这样的字符串 它是组件的属性 p test 2 bla bla p p test1234 56 p p test test p 所以 我按照文档进行操作 https angular io guide te
  • 有没有办法知道哪个编译器生成了静态库?

    第三方为我提供了一个静态库 a 用于在 Solaris 站上链接 我尝试使用 sunpro 进行编译 但在链接步骤失败 我想这个问题来自我使用的编译器 而不是 gcc 或者只是它的版本 因为编译器提供的 std lib 可能会从库预期的版本
  • opencv多通道元素访问

    我正在尝试学习如何使用 OpenCV 的新 C 界面 如何访问多通道矩阵的元素 例如 Mat myMat size 3 3 CV 32FC2 for int i 0 i lt 3 i for int j 0 j lt 3 j myMat a
  • 如何计算两个日期之间的年龄/年数[重复]

    这个问题在这里已经有答案了 可能的重复 如何在 T SQL 中用年 月 日计算年龄 https stackoverflow com questions 57599 how to calculate age in t sql with yea
  • 如何在传单地图上添加搜索框

    我想使用传单地图作为页面的背景 并且这个页面有搜索功能 但是这个搜索框并不是用来搜索这张地图的 所以我的问题是如何在传单地图上添加搜索框 您还有其他解决方案使用地图作为背景吗 喜欢这个页面 http directory spatineo c
  • 使用 doLast 的 Gradle 执行任务失败

    仅当文件自上次构建以来已更新时 我才尝试运行执行任务 我最初的尝试是这样的 task generateLocalizedStrings type Exec ext srcFile file localization language fil
  • MVC 查看可为空的日期字段格式

    我试图在视图中显示以下内容 但出现问题 td item CreatedByDt ToString MM dd yyyy td 关于如何处理视图中可为空的日期字段的任何想法 顺便说一句 我正在使用 Razor 我收到以下错误 方法 ToStr
  • 减少 solr 结果输出中类似的顶部结果

    我在 solr 中进行了一次搜索 返回了大约 1500 个文档 这些文档基本上都是产品 例如 我的数据集中有一堆女鞋 我的数据集有各种各样的女鞋 但也有一些非常相似的结果 例如 11 号女式耐克运动鞋 10 号女式耐克运动鞋等 现在 当我搜
  • PDFBOX - 使用 easytable 的所有页面中的页眉

    我正在使用 pdfbox 和 easytablehttps github com vandeseer easytable https github com vandeseer easytable用于创建效果很好的动态页面 但我确实希望在所有
  • Matplotlib 多条动画多行

    我一直在研究如何为飞行路径制作多条线的动画 我读取多个 GPS 文件的对象是时间同步它们 它们相对于时间为每条路径设置动画 我找到了如何在动画函数中使用附加来为一行添加动画 现在我需要添加第二个和第三个 以便导入尽可能多的文件 我知道问题出
  • 无法在有关 iron lib 的 fn 项目中捕获动态环境

    我使用c c 驱动的cassandra来查询 然后返回数据 因此 cass LinkedList 和cass it Vec 都可以显示查询的结果 但是 我想使用json格式将结果显示到web上 所以我选择使用vec重新组装数据 然而 有一个
  • 使用并行 NetCDF 保存分布式 3D 复杂数组

    我有一个用 Fortran 编写的基于 MPI 的程序 它在每个节点 2D 时间序列的部分 生成复杂数据的 3D 数组 我想使用并行 I O 将这些数组写入单个文件 该文件可以相对轻松地在 python 中打开以进行进一步分析 可视化 理想