为什么Fortran可以分配这么大的数组?

2023-12-02

我编写了一段科学代码,像往常一样,这归结为计算代数特征值方程中的系数:计算这些系数需要对多维数组进行积分,这会迅速大幅增加内存使用量。一旦计算出矩阵系数,就可以释放原始的预积分多维数组,并由智能求解器接管,因此内存使用不再是大问题。正如您所看到的,存在瓶颈,在我的 64 位、4 核、8 线程、8GB 内存笔记本电脑上,程序因内存不足而崩溃。

因此,我正在实现一个系统,通过限制 MPI 处理在计算某些特征值矩阵元素时可以承担的任务的大小来控制内存使用情况。完成后,他们将寻找剩余的工作来完成,以便矩阵仍然被填充,但以更顺序和更少并行的方式。

因此,我正在检查可以分配多少内存,这就是混乱开始的地方:我分配了大小为 8 字节的双精度数(使用sizeof(1))并查看分配状态。

虽然我有 8 GB 的可用内存来运行仅 1 个进程的测试,但我可以分配一个最大大小的数组(40000,40000),大约对应13GB内存!我的第一个问题是:这怎么可能?虚拟内存有这么多吗?

其次,我意识到我也可以对多个进程做同样的事情:最多16流程可以,同时地分配这些巨大的数组!

这不可能吧?

有人明白为什么会发生这种情况吗?我是否做错了什么?

Edit:

这是产生上述奇迹的代码,至少在我的机器上是这样。然而,当我将数组的元素设置为某个值时,它确实会按其应有的方式运行并崩溃——或者至少开始运行very缓慢,我猜这是因为使用了缓慢的虚拟内存?

program test_miracle
    use ISO_FORTRAN_ENV
    use MPI

    implicit none

    ! global variables
    integer, parameter :: dp = REAL64                                           ! double precision
    integer, parameter :: max_str_ln = 120                                      ! maximum length of filenames
    integer :: ierr                                                             ! error variable
    integer :: n_procs                                                          ! MPI nr. of procs

    ! start MPI
    call MPI_init(ierr)                                                         ! initialize MPI
    call MPI_Comm_size(MPI_Comm_world,n_procs,ierr)                             ! nr. MPI processes
    write(*,*) 'RUNNING MPI WITH', n_procs, 'processes'

    ! call asking for 6 GB
    call test_max_memory(6000._dp)
    call MPI_Barrier(MPI_Comm_world,ierr)

    ! call asking for 13 GB
    call test_max_memory(13000._dp)
    call MPI_Barrier(MPI_Comm_world,ierr)

    ! call asking for 14 GB
    call test_max_memory(14000._dp)
    call MPI_Barrier(MPI_Comm_world,ierr)

    ! stop MPI
    call MPI_finalize(ierr)

contains
    ! test whether maximum memory feasible
    subroutine test_max_memory(max_mem_per_proc)
        ! input/output
        real(dp), intent(in) :: max_mem_per_proc                                ! maximum memory per process

        ! local variables
        character(len=max_str_ln) :: err_msg                                    ! error message
        integer :: n_max                                                        ! maximum size of array
        real(dp), allocatable :: max_mem_arr(:,:)                               ! array with maximum size
        integer :: ierr                                                         ! error variable

        write(*,*) ' > Testing whether maximum memory per process of ',&
            &max_mem_per_proc/1000, 'GB is possible'

        n_max = ceiling(sqrt(max_mem_per_proc/(sizeof(1._dp)*1.E-6)))

        write(*,*) '   * Allocating doubles array of size', n_max

        allocate(max_mem_arr(n_max,n_max),STAT=ierr)
        err_msg = '   * cannot allocate this much memory. Try setting &
            &"max_mem_per_proc" lower'
        if (ierr.ne.0) then
            write(*,*) err_msg
            stop
        end if

        !max_mem_arr = 0._dp                                                     ! UNCOMMENT TO MAKE MIRACLE DISSAPEAR


        deallocate(max_mem_arr)

        write(*,*) '   * Maximum memory allocatable'
    end subroutine test_max_memory
end program test_miracle

要保存在test.f90然后编译并运行

mpif90 test.f90 -o test && mpirun -np 2 ./test

当你做一个allocate声明,您在虚拟内存空间中保留一个域。虚拟空间是物理内存+交换空间+可能由于某些原因而产生的额外可能空间的总和过度使用假设您不会使用所有预订的可能性。

但在您向其中写入内容之前,内存尚未被物理保留。当你向内存中写入内容时,系统会物理上为你分配相应的页面。 如果您不初始化数组,并且数组非常稀疏,则可能有许多页面从未被写入,因此内存永远不会在物理上得到充分使用。

当您看到系统速度变慢时,可能是系统正在将页面交换到磁盘,因为物理内存已满。如果你有 8GB RAM 和 8GB 磁盘交换空间,你的计算就可以运行(非常慢......)

这种机制在 NUMA 环境中非常好,因为这种“首次接触策略”将分配靠近首先写入的 CPU 的内存。 通过这种方式,您可以在 OpenMP 循环中初始化数组,以将内存物理放置在靠近将使用它的 CPU 的位置。

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

为什么Fortran可以分配这么大的数组? 的相关文章

  • 为什么MIPS中内存地址加4?

    如果某些内容存储在 0x1001 0000 处 则下一个内容将存储在 0x1001 0004 处 如果我是正确的 32 位架构中的内存块每个都是 32 位 那么0x1001 0002会指向32位的后半部分吗 首先 MIPS 架构中的内存地址
  • printf() var-arg 引用如何与堆栈内存布局交互?

    给出代码片段 int main printf Val d 5 return 0 是否有任何保证编译器会存储 Val d and 5 连续地 例如 d l a V 5 Format String
  • 纯 Fortran 过程中的 I/O

    我正在尝试将错误检查合并到我正在编写的纯过程中 我想要这样的东西 pure real function func1 output unit a implicit none integer a output unit if a lt 0 th
  • RenderTargetBitmap 内存泄漏

    我正在尝试使用 RenderTargetBitmap 渲染图像 每次我从 RenderTargetBitmap 创建一个实例来渲染图像时 内存都会增加 完成后内存永远不会释放 这是代码 RenderTargetBitmap rtb new
  • 如何查找或计算Linux进程的页表大小和其他内核占用?

    我怎样才能知道 Linux 进程页表有多大 以及任何其他可变大小的进程统计 如果您真的对页表感兴趣 请执行以下操作 cat proc meminfo grep PageTables PageTables 24496 kB
  • C语言中变量名是如何存储在内存中的?

    在 C 中 假设你有一个名为variable name 假设它位于0xaaaaaaaa 在该内存地址处 您有整数 123 换句话说 variable name包含 123 个 我正在寻找有关措辞的澄清 variable name位于0xaa
  • WPF 窗口关闭后不会释放内存

    我创建了一个测试代码 private void Application Startup 1 object sender StartupEventArgs e ShutdownMode System Windows ShutdownMode
  • 从 QML 实例化 C++ 对象会产生巨大的内存使用开销

    实例化一个QObjectC 堆中的派生类为每个对象提供了大约 160 个字节 通过注册相同的对象qmlRegisterType 用于从 QML 创建并通过以下方式动态创建对象createObject 每个对象给我 2000 多个字节 这是完
  • Codeigniter 处理大文件时允许的内存大小耗尽

    我发布此内容是为了防止其他人正在寻找相同的解决方案 因为我刚刚在这个废话上浪费了两天时间 我有一个 cron 作业 每天使用一个非常大的文件更新数据库一次 使用以下代码 if handle fopen dirname FILE uncomp
  • 如何防止字符串被截留

    我的理解 可能是错误的 是 在 C 中 当你创建一个字符串时 它会被实习到 实习生池 中 这保留了对字符串的引用 以便多个相同的字符串可以共享操作内存 但是 我正在处理很多很可能是唯一的字符串 一旦完成每个字符串 我需要将它们从操作内存中完
  • 当结构体包含字符串时为其分配内存

    假设如果我有一个这样的结构 struct node note that i have changed the struct code according to my convenience char lastname char employ
  • 操作系统什么时候清除进程的内存

    进程在某些操作系统上成功或异常终止 操作系统何时决定擦除分配给该进程的内存 数据 代码等 在退出时或当它想为新进程分配内存时 这个清除内存分配过程在所有操作系统 winXP Win7 linux Mac 上都相同吗 据我了解 页表具有该进程
  • 在 python 中将变量设置为“None”是否更节省内存?

    这是一个简单的问题 但由于我没有找到任何答案 我认为答案是否定的 但是 为了确保这一点 我要问 将变量设置为是否会使Python代码更有效None当我们在函数中使用完它们之后 举个例子 def foo fname temp 1 temp 2
  • Objective-C 使用字符串池吗?

    我知道Java https stackoverflow com questions 3801343 what is string pool in java and C http msdn microsoft com en us librar
  • UseCompressedOops JVM 标志有什么作用以及何时应该使用它?

    HotSpot JVM 标志是什么 XX UseCompressedOops我应该做什么以及什么时候使用它 在 64 位 Java 实例上使用它 与不使用它 时 我会看到什么样的性能和内存使用差异 去年大多数 HotSpot JVM 都默认
  • Android 性能:SharedPreferences 的成本

    当我的应用程序启动时 我使用分片首选项中的值填充容器类 这个想法是处理 SharedPreferences 和 PreferenceManager 一次 因为我猜它们很重 这是一个示例 SharedPreferences prefs Pre
  • 跟踪 Linux 程序中活跃使用的内存

    我想跟踪各种程序在特定状态下接触了多少内存 例如 假设我有一个图形程序 最小化时 它可能会使用更少的内存 因为它不会重新绘制窗口 这需要读取图像和字体并执行大量库函数 这些对象仍然可以在内存中访问 但实际上并没有被使用 类似的工具top它们
  • 如何计算选择查询的最佳获取大小

    在 JDBC 中 默认获取大小为 10 但我想当我有一百万行时 这不是最佳获取大小 据我所知 获取大小太低会降低性能 但如果获取大小太高也会降低性能 我怎样才能找到最佳尺寸 这对数据库端有影响吗 它会占用大量内存吗 如果您的行很大 请记住
  • 应用程序无缘无故地被杀死。怀疑 BSS 高。如何调试呢?

    我已经在CentOs6 6中成功运行我的应用程序 最近 硬件 主板和内存 更新了 我的应用程序现在毫无理由地被杀死 root localhost PktBlaster PktBlaster Killed 文件和 ldd 输出 root lo
  • iOS 视图控制器内存在被关闭后未释放

    当用户单击按钮时 它会显示一个带有两个视图控制器的新选项卡栏视图控制器 我是这样做的 ACLevelDownloadController dvc ACLevelDownloadController alloc initWithNibName

随机推荐

  • 循环依赖

    我有 2 个项目 项目 2 引用了项目 1 现在我需要在 Project 1 中引用 Project 2 但 vs net 抱怨循环依赖 有办法解决这个问题吗 绝对不 循环依赖是糟糕设计的表现 我并不是有意严厉 有一些方法可以解决这个问题
  • Gtk# 剪贴板复制/剪切/粘贴文件

    如何使用 Gtk 复制 剪切和粘贴文件到剪贴板 我见过的每个例子都只显示文本被放入剪贴板 如果有人有一个例子 我将不胜感激 如果您的应用程序在 Gnome Unity 上运行 您可以使用 x special gnome copied fil
  • 我可以将编译时策略的创建和使用位置分开吗?

    include
  • SQL IF SELECT 查询为空然后执行另一个查询

    我有一个定期返回 无 的查询 如果是这种情况 我想运行不同的查询 但我不知道执行此操作的方法 如果有人可以帮忙的话 这是我当前使用的代码 SELECT FROM cfg users JOIN cfg ash ON cfg users iUs
  • xcode4中框架和静态库的区别以及如何调用

    我对 Xcode 和 Objective C 很陌生 我想问一个非常基本的问题 我看到在项目设置中 将二进制文件链接到库 时 从工作区中的其他项目导入的框架和库存在差异 第一个问题 为什么要有框架 为什么会有图书馆 我的库不能成为一个框架吗
  • FacesServlet URL 模式

    我不确定我在这里做错了什么 但是当我在 URL 中放置两次面孔上下文时 它会绕过我的所有 Realm 证券 我的网址模式
  • 在 Ubuntu 中运行多个独立的 Flask 应用

    我正在尝试使用 Apache 在单独的虚拟目录中运行两个或多个 Flask 应用程序 例如http localhost site1 for var www myapps app1 and http localhost site2 for v
  • heroku db:pull 无法连接到我在 ubuntu 中的数据库

    所以我最近将ubuntu更新到11 04 然后又降级回11 04 因为我讨厌unity 不管怎样 在我重新安装 11 40 后 我必须克隆所有旧的 Heroku 应用程序并尝试运行heroku db pull拉取数据库并将其导入到我的 my
  • 如何从 iPhone 中的 Web 服务获取数据?

    我必须开发一个应用程序 其中包括以下内容 gt 通过 iPhone 向 Web 服务发出请求 gt 从网络服务获取数据 我从未使用过 Web 服务来开发 iPhone 应用程序 但我知道什么是网络服务 The example of web
  • Git 正在转向新的哈希算法 SHA-256,但为什么 git 社区选择 SHA-256

    我刚刚从这件事中学到了HN postgit 正在转向新的哈希算法 从SHA 1 to SHA 256 我想知道是什么让SHA 256最适合 git 的用例 是否有任何 许多强有力的技术原因或者是否有可能SHA 256人气是一个强大的因素吗
  • Android Studio:无法完成 gradle 执行,原因为空

    当我尝试运行 Android 模拟器时 出现以下错误屏幕 当我导出 apk 时也会发生同样的情况 当我转到保存 apk 的目录时 apk 文件不存在 谢谢你 克里斯托夫 我遇到了同样的问题 通过执行以下步骤可以解决此问题 Go to 文件
  • 如何获取 Chrome 扩展程序子文件夹中的文件名列表?

    我想知道是否可以获取 Chrome 扩展程序的子文件夹中所有文件的文件名列表 谢谢你 Use the chrome runtime getPackageDirectoryEntry方法得到一个DirectoryEntry对于 Chrome
  • 将自定义角色分配给 Azure Active Directory 系统托管标识

    为了在 API 之间建立 Azure AD 系统托管标识 我在应用程序清单中为目标 API 定义了一个自定义角色 appRoles allowedMemberTypes Application description Allow the a
  • 在 C# 中测试/注入私有字段的良好做法是什么

    如果这是重复的 我很抱歉 我被赋予了为该方法添加一些覆盖范围的任务 并被告知要模拟私有的List
  • PHP 中的数字格式

    我想将带小数位的数字格式化为不带小数位的格式 例如 146 5 到 146500000 我如何在 PHP 中实现这一点 谢谢 乘以100000 没那么容易
  • 在 Excel 中导入 CSV 美国格式的数字并进行本地化?

    我有一个包含以下值的 csv 文件 1488201602 653 8 304700E 04 3 079498E 03 1488201603 107 8 677357E 04 2 856719E 03 1488201821 012 7 071
  • 另一个线性渐变内的线性渐变

    我正在尝试在另一个线性渐变中创建线性渐变 这可能吗 下面的例子 background linear gradient to right color1 50 color2 0 颜色 1 是 background linear gradient
  • ARM Aarch64 中的 PUSH {lr} 和 POP {lr}

    等效指令是什么PUSH lr and POP lr 在ARM Aarch64指令集中 Is STR X30 SP 8 正确的 您能解释一下维护堆栈对齐的概念吗 我对 ARMv8 比较陌生 所以请原谅 如果您要求 C 编译器从源代码生成汇编语
  • WIX 自定义操作:使用 dllimport

    我有一个 WiX 安装程序和自定义操作项目 我添加了 C 库作为自定义操作项目的参考 此 C dll 使用 DllImport 到一个 C dll 安装时收到错误 无法加载 DLLmycpp dll 未找到指定的模块 我添加了mycpp d
  • 为什么Fortran可以分配这么大的数组?

    我编写了一段科学代码 像往常一样 这归结为计算代数特征值方程中的系数 计算这些系数需要对多维数组进行积分 这会迅速大幅增加内存使用量 一旦计算出矩阵系数 就可以释放原始的预积分多维数组 并由智能求解器接管 因此内存使用不再是大问题 正如您所