2013-10-15 4 views
2

Я сталкиваюсь с проблемами точности с MPI_REDUCE() в fortran. Я проверил два метода суммирования чисел двойной точности, хранящихся на каждом узле. Линии MPI_REDUCE() я используюТочные проблемы с MPI_REDUCE

call MPI_REDUCE(num,total,1,MPI_DOUBLE_PRECISION,MPI_SUM,0,MPI_COMM_WORLD,ierr) 

, который хранит сумму значений «пит» на каждое ядро ​​и отправляет его на «всего» на корневом ядре.

Другой метод я использую включает передачу и прием

if (rank .eq. 0) total = num 
do i = 1,nproc-1 
    if (rank .eq. i) call MPI_SEND(num,1,MPI_DOUBLE_PRECISION,0,& 
            100,MPI_COMM_WORLD,ierr) 
    if (rank .eq. 0) then 
     call MPI_RECV(num,1,MPI_DOUBLE_PRECISION,i,& 
         100,MPI_COMM_WORLD,stat,ierr) 
     total = total + num 
    end if 
end do 

Последние всегда дает мне тот же номер для общей сложности, в то время как бывшие производит различное значение в зависимости от количества процессоров, которые я использую (Это обычно изменяется на 1x10^-5 или около того). ierr = 0 во всех случаях. Я делаю что-то неправильно?

Благодаря

ответ

3

арифметики с плавающей точкой не является строго ассоциативная, порядок, в котором выполняются операции могут иметь влияние на результат. В то время как

(a+b)+c == a+(b+c) 

верно для реальной (как в математическом, а не Fortran, терминологии) чисел это не так (универсально) справедливо для чисел с плавающей точкой. Поэтому неудивительно, что встроенное сокращение приводит к результату, который отличается от вашего собственного сокращения, сокращенного на дому. Поскольку вы меняете количество процессоров, у вас нет контроля над порядком отдельных дополнений в вычислении; даже на фиксированном числе процессоров я бы не удивился небольшой разнице между результатами разных исполнений одной и той же программы. Напротив, ваше собственное сокращение всегда делает дополнения в том же порядке.

Какова относительная ошибка двух результатов? В исходной точке 10^(-5) указывается только абсолютная ошибка, и это не позволяет сделать вывод о том, что ваша ошибка может быть полностью объяснена неассоциативностью арифметики f-p.

+0

Спасибо за ответ. Вот пример. Для 4 ядер каждый хранит один из следующих номеров. -.016578650712928463 -.005729268089031345 -.012569993133665655 -.055321271877137639 Мой метод отправки/RECV дает результат -9.0199183812763095E-002 Метод MPI_REDUCE дает результат -9.0199110912786068E-002 Mathematica соглашается с моим методом send/recv. Еще раз спасибо – DJames

+0

Не только это, но и 'MPI_SUM' и все другие предопределенные операторы сокращения MPI также ** коммутативны **, и поэтому аргументы суммирования могут быть спарены в любом порядке. –