我有一个关于openMP内存分配的问题(语言:Intel Fortran)。我写了一个程序并用两台不同的机器进行了测试。它包含一个openMP并行化的DO LOOP,它基本上是程序的核心,占用了大部分的计算时间。
首批机器规格为Intel Xeon X5690(2个处理器,2个6核,3.47 GHz,40 Gb)。该计划在34米内顺利运行。第二个是(或至少应该)在规格(英特尔至强E5,28核心和所有爵士乐)方面表现更好。然而,令人惊讶的是,该程序在第二个工作站上运行大约3小时30分钟。然后我建议用CrayPat对其进行分析,结论是分配,释放和释放内存所需的时间占用了80%的计算时间,因为DO LOOP内部调用的一些函数必须分配一些(不太大)的数组。然后我决定重写程序,避免几乎所有这些分配(我只是在DO LOOP开始之前分配了所有变量)。我重复了相同的测试,我得到第一台机器需要3小时30分才能运行整个程序,第二台机器需要4小时30分钟。
最令人惊讶的是,如果我只使用一个线程(第一个版本,而不是修改版本)运行程序,则第二个机器比第一个机器快(大约3h30m vs 2h50m)!
可能有必要补充说,该程序包含四精度复杂操作,并且未应用任何优化选项(英特尔Fortran默认)。
我想知道为什么会出现这么大的差异,你建议我做些什么来加速第二台机器上的程序?很明显,第二台机器中的OpenMP以与我预期的“不同”方式处理内存。
答案 0 :(得分:1)
我解决了这个问题。这是因为在子程序中我有所有复杂的操作,而如果所有其他子程序和主程序我都为每个复数使用了一个双元素数组。通过将两个元素阵列更改为几个标量,我得到了计算解决方案所需的时间在第一台机器上减少到26米(相对于34米),在第二台机器上减少到25米(相比大约4小时30分钟)。毫无疑问,对整个程序使用COMPLEX类型而不是几个arryas可能是未来的一个很好的解决方案。 谢谢大家。
答案 1 :(得分:0)
嗯,OpenMP与内存分配没有任何关系。
也许您分配内存的方式转换为错误的共享问题。
对于我而言,发现28核机器比12核机器慢,并不奇怪。
如果您有许多内核并且分配了大量内存,具体取决于您执行此操作的方式和使用的数据分解,则可能会在内核之间生成大量通信。您拥有的核心越多,您生成的流量就越多。特别是如果您没有正确对齐内存分配以避免cache thrashing。
在进入循环之前分配所有变量也会降低程序的速度,因为分配是完全串行而不是并行化。当前的动态内存实现使用锁来保护内存分配,但它们还保留内部内存池以避免不断进入内核模式,从而允许更好的并发访问,从而减少争用。
为了更好地使用28核心机器,我的一般建议是在DO LOOP内正确并行化内存分配并正确分区数据。线程必须尽可能少地干涉。根据你的帖子,这似乎是该计划的瓶颈。