【问题标题】:OpenMP Memory AllocationOpenMP 内存分配
【发布时间】:2015-05-16 15:34:27
【问题描述】:

我有一个关于 openMP 内存分配的问题(语言:Intel Fortran)。我编写了一个程序并用两台不同的机器对其进行了测试。它包含一个 openMP 并行 DO LOOP,它基本上是程序的核心,占用了大部分计算时间。

第一个机器规格是 Intel Xeon X5690(2 个处理器,2x6 核,3.47 GHz,40 Gb)。程序在 34m 内顺利运行。第二个在规格(英特尔至强 E5、28 核和所有爵士乐)方面(或至少应该)性能要好得多。然而,令人惊讶的是,该程序在第二个工作站上运行了大约 3 小时 30 分。然后我被建议使用 CrayPat 对其进行分析,结果是分配、解除分配和释放内存所需的时间占了计算时间的 80%,因为在 DO LOOP 中调用的某些函数必须分配一些(不太大的)数组。然后我决定重写程序,避免几乎所有这些分配(我只是在 DO LOOP 开始之前分配了所有变量一次)。我重复了同样的测试,我发现第一台机器运行整个程序需要 3 小时 30 分钟,而第二台机器大约需要 4 小时 30 分钟。

最令人惊讶的是,如果我只用一个线程运行程序(第一个版本,而不是修改过的那个),第二台机器比第一台机器更快(大约 3 小时 30 分钟对 2 小时 50 分钟)!

可能需要添加该程序包含四精度复杂运算并且未应用优化选项(英特尔 Fortran 默认设置)。

我想知道为什么会出现如此巨大的差异,你会建议我做些什么来加快第二台机器上的程序?很明显,第二台机器中的 OpenMP 处理内存的方式与我的预期“不同”。

【问题讨论】:

  • 当所有其他时间都是多个小时时,我对第一个“在 34m 内平稳运行”感到困惑。错字?
  • 亲爱的蒂姆迪! 34 分钟没有错别字。我今天再次运行相同的程序,仍然得到相同的时间。我显然得到了所有测试的相同数据。我唯一改变的是makefile。第一个工作站在 windows 环境下运行,而第二个在 linux 环境下运行。
  • 亲爱的马克,system_clock。我测量的是挂钟时间,而不是 CPU 时间。我确信时间的正确性,因为我一直在监控计算。老实说,我不确定在并行线程的情况下 cpu_time 指的是什么,所以我避免了它。顺便说一句,两个计算中的线程数相同(12)。
  • 使用标签fortran获得更多关注。

标签: memory-management parallel-processing fortran openmp intel-fortran


【解决方案1】:

我解决了这个问题。这是因为在一个子程序中我有所有复杂的操作,而如果所有其他子程序和主程序我对每个复数都使用了一个二元素数组。通过将两个元素数组更改为几个标量,我发现在第一台机器上计算解决方案所需的时间减少到 26m(vs 34m),在第二台机器上减少到 25m(vs 大约 4h30m)。毫无疑问,在整个程序中使用 COMPLEX 类型而不是几个 arrya 可能是未来的一个很好的解决方案。 谢谢大家。

【讨论】:

    【解决方案2】:

    嗯,OpenMP 与内存分配没有任何关系。

    也许您分配内存的方式会导致错误的共享问题。

    此外,我发现 28 核机器比 12 核机器慢也不足为奇。

    如果您有很多内核并且要分配大量内存,则取决于您执行此操作的方式和正在使用的数据分解,您可能会在内核之间产生大量通信。您拥有的核心越多,您产生的流量就越多。特别是如果您没有正确对齐内存分配以避免cache thrashing

    在进入循环之前分配所有变量也会减慢程序的速度,因为分配是完全串行完成的,而不是并行完成的。当前的动态内存实现使用锁来保护内存分配,但它们还保留内部内存池以避免不断进入内核模式,从而允许更好的并发访问,减少争用。

    为了更好地使用 28 核机器,我的一般建议是正确并行化 DO LOOP 内的内存分配并正确分区数据。线程必须尽可能少地干扰。根据您的帖子,这似乎是程序的瓶颈。

    【讨论】:

      猜你喜欢
      • 2017-07-11
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      • 2011-09-03
      • 1970-01-01
      • 1970-01-01
      • 2011-05-25
      相关资源
      最近更新 更多