我在笔记本电脑上运行MPI(intel i7四核4700m 12Gb RAM),即使对于不涉及进程间通信的代码,效率也会下降。显然我不能只抛出100个进程,因为我的机器只是四核,但我认为它应该可以扩展到8个进程(intel四核模拟为8 ???)。例如,考虑简单的玩具Fortran代码:
program test
implicit none
integer, parameter :: root=0
integer :: ierr,rank,nproc,tt,i
integer :: n=100000
real :: s=0.0,tstart,tend
complex, dimension(100000/nproc) :: u=2.0,v=0.0
call MPI_INIT(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,nproc,ierr)
call cpu_time(tstart)
do tt=1,200000
v=0.0
do i=1,100000/nproc
v(i) = v(i) + 0.1*u(i)
enddo
enddo
call cpu_time(tend)
if (rank==root) then
print *, 'total time was: ',tend-tstart
endif
call MPI_FINALIZE(ierr)
end subroutine test2
对于2个过程,它需要一半的时间,但即使尝试4个过程(应该是四分之一的时间?),结果开始变得效率降低,对于8个过程,没有任何改进。基本上我想知道这是不是因为我在笔记本电脑上运行并且与共享内存有关,或者我在代码中犯了一些根本性的错误。感谢
注意:在上面的例子中,我手动将数组声明中的nproc和内部循环更改为等于我正在使用的处理器数。
答案 0 :(得分:1)
四核处理器,由于超线程显示自己有8个线程,但实际上它们只有4个核心。其他4个由硬件本身使用执行流水线中的空闲槽调度。
特别是对于计算密集型负载,这种方法根本不付费,在极端负载下通常也会产生效率,因为开销并不总是优化缓存使用。
您可以尝试在BIOS中禁用超线程并进行比较:您将只有4个线程,4个核心。
即使从1到4,也有竞争资源。特别是每个内核都有自己的L1缓存,但每对内核共享L2缓存(2x256KB),4个内核共享L3缓存。
所有内核显然共享内存通道。
因此,您不能指望线性扩展占用越来越多的内核,因为它们必须平衡资源的使用,这些资源专用于顺序情况下的一个核心/一个线程。
所有这一切都没有涉及通信。
在桌面/服务器上发生相同的行为,特别是对于内存密集型负载,就像测试用例中那样。
例如,矩阵矩阵乘法不太明显,即计算密集型:对于NxN矩阵,您有O(N ^ 2)个存储器访问但O(N ^ 3)浮点运算。