В настоящее время я работаю над добавлением распараллеливания openmp для цикла do в одном из кодов, которые я написал для исследования.Я довольно новичок в использовании openmp, поэтому я был бы признателен, если бы у вас были какие-либо предложения о том, что может пойти не так.
По сути, я добавил параллельный цикл do в следующий код (который работает до распараллеливания).r (:,:,:, :) - это вектор тонны молекулярных координат, проиндексированных по времени, молекуле, атому и (xyz).Этот вектор составляет около 100 ГБ данных (я работаю на HPC с большим количеством оперативной памяти).Я пытаюсь распараллелить внешний цикл и поделить его между процессорами, чтобы сократить время выполнения этих вычислений.Я подумал, что было бы неплохо сделать это, так как msd и cm_msd - единственные вещи, которые должны быть отредактированы несколькими процессорами и сохранены для последующего использования, так как каждая итерация получает свой собственный элемент этих массивов, которых у них не будетусловие гонки.
Проблема: если я запускаю этот код 5 раз, я получаю разные результаты, иногда MSD рассчитывается правильно (или кажется), и иногда он выводит все нули позже, когда я усредняю его вместе.Без распараллеливания нет проблем.
Я пытался изменить общие и частные переменные в коде, и я думаю, что я все учел.Индекс i массива msd и массива msd_cm никогда не должен быть эквивалентным между потоками, поэтому я думаю, что они не будут проблемой.
! Loop over time origins
counti = 0
ind = 0
!$OMP PARALLEL DO schedule(static) PRIVATE(i,j,k,it,r_old,r_cm_old,shift,shift_cm,dsq,ind) &
!$OMP& SHARED(msd,msd_cm)
do i=1, nconfigs-nt, or_int
if(MOD(counti*or_int,500) == 0) then
write(*,*) 'Reached the ', counti*or_int,'th time origin'
end if
! Set the Old Coordinates
counti = counti + 1
ind = (i-1)/or_int + 1
r_old(:,:,:) = r(i,:,:,:)
r_cm_old(:,:) = r_cm(i,:,:)
shift = 0.0
shift_cm = 0.0
! Loop over the timesteps in each trajectory
do it=i+2, nt+i
! Loop over molecules
do j = 1, nmols
do k=1, atms_per_mol
! Calculate the shift if it occurs.
shift(j,k,:) = shift(j,k,:) - L(:)*anint((r(it,j,k,:) - &
r_old(j,k,:) )/L(:))
! Calculate the square displacements
dsq = ( r(it,j,k,1) + shift(j,k,1) - r(i,j,k,1) ) ** 2. &
+( r(it,j,k,2) + shift(j,k,2) - r(i,j,k,2) ) ** 2. &
+( r(it,j,k,3) + shift(j,k,3) - r(i,j,k,3) ) ** 2.
msd(ind, it-1-i, k) = msd(ind, it-1-i, k) + dsq
! Calculate the contribution to the c1,c2
enddo ! End Atoms Loop (k)
! Calculate the shift if it occurs.
shift_cm(j,:) = shift_cm(j,:) - L(:)*anint((r_cm(it,j,:) - &
r_cm_old(j,:) )/L(:))
! Calculate the square displacements
dsq = ( r_cm(it,j,1) + shift_cm(j,1) - r_cm(i,j,1) ) ** 2. &
+( r_cm(it,j,2) + shift_cm(j,2) - r_cm(i,j,2) ) ** 2. &
+( r_cm(it,j,3) + shift_cm(j,3) - r_cm(i,j,3) ) ** 2.
msd_cm(ind,it-1-i) = msd_cm(ind, it-1-i) + dsq
enddo ! End Molecules Loop (j)
r_old(:,:,:) = r(it,:,:,:)
r_cm_old(:,:) = r_cm(it,:,:)
enddo ! End t's loop (it)
enddo
!$OMP END PARALLEL DO
Когда этот код запускается, когда я позже печатаю усредненноеMSD приводит к тому, что они либо выходят как правильно, либо выходят как ноль, и это всегда один или другой.Видите ли вы проблему, которая может объяснить, почему это работает только часть времени.Я новичок в openmp, поэтому вполне возможно, что что-то невероятно глупое в том, как я пытаюсь это сделать.
Заранее спасибо!