2014-04-04 2 views
1

MPI 루틴을 사용하는 데 비교적 익숙하지 않으며 아래 코드에서 내가 사용하는 노드 수에 따라 다른 결과를 얻는 이유에 대해 혼란 스럽습니다.MPI4PY : 다른 수의 노드가 다른 결과를 반환합니다.

코드 :

import numpy as np 
from mpi4py import MPI 

def MPI_sum(comm,x): 
    xsum = np.sum(x) 
    vals = comm.gather(xsum,root=0) 

    if rank == 0: 
     s = np.sum(vals) 

    s = comm.bcast(s,root=0) 

    return s 

comm = MPI.COMM_WORLD 
size = comm.Get_size() 

datalen = 80000/size 
x = np.zeros(datalen) + 1. + 1e-5 

xsum = MPI_sum(comm,x) 
if rank == 0: 
    print xsum - np.floor(xsum) 

나는 1 개 노드와 2 개 노드와이 코드를 실행. 1 노드에서 얻은 대답은 다음과 같습니다. 0.800000153016 2 노드에서 얻은 대답은 0.800000035219

입니다.이 불일치의 원인은 무엇입니까?

(덧붙여서 MPI_sum에있는 x 배열 데이터를 모두 root = 0으로 전달한 다음 root = 0으로 합산하여 올바른 답을주었습니다. 노드 수에 관계없이 같은 결과가 나타납니다. 그러나 하나의 노드에 모든 데이터를 전달하는 코드는 실용적이지 않습니다.이 코드는 구현할 것입니다.

도움을 주셔서 감사합니다!

답변

3

관찰 된 효과는 부동 소수점 연산의 비 연관성으로 인해 발생하며 MPI 응용 프로그램에만 해당되는 것은 아니지만 후자는 문제 도메인의 분할로 인해 더 자주 노출되는 경향이 있습니다. 무슨 생각 얻기 위해 다음 사항을 준수하십시오 전체 배열이 동일하지 않습니다 합산, 유한 정밀 컴퓨터 주어, 즉

>>> import numpy as np 
>>> datalen = 80000 
>>> x = np.zeros(datalen) + 1. + 1e-5 
>>> xsum = np.sum(x) 
>>> xsum - np.floor(xsum) 
0.80000015301629901 
>>> xsum = np.sum(x[:datalen/2]) + np.sum(x[datalen/2:]) 
>>> xsum - np.floor(xsum) 
0.80000003521854524 

먼저 별도로 배열의 두 반쪽을 합산 한 후이 둘을 합산로 MPI (코드에서와 같이)를 사용하거나 직렬로 (예에서와 같이) 사용하면 상관 없습니다.

이유는 두 개의 부동 소수점 숫자가 함께 추가 될 때마다 마지막 비트 반올림이 수행되기 때문입니다. 시간이 흐르면 ​​부동 소수점 연산의 특징을 처리합니다. 유사한 효과를 방지하는 특수 합계 알고리즘이 있습니다 (예 : Kahan summation algorithm. 10 -5 로그 보낸 모든 유한 정밀 진 컴퓨터 정확하게 표현할 수 없다

하는 것으로 2 (10 -5는) -5- X 2 (10)에 로그인하고 이진 대수 = 10은 불합리한 숫자입니다.

+0

64 비트 부동 소수점을 사용할 때 2^64 (10^19) 개의 유효 숫자가 아닌 10^10의 순서 여야합니다. – Bremsstrahlung

+0

정수 부분에는 5 자리가 있고 7 자리에는 소수 부분이 다릅니다. 정확도는 12 자리입니다. 나머지는 80000 (~ 10^6) 개의 숫자를 합산하는 동안 반올림 오류로 인해 손실됩니다. Kahan 알고리즘의 결과와 비교하십시오. –

관련 문제