LINUX.ORG.RU

вложенные циклы в openmp

 , ,


0

1

что-то совсем запутался. у меня есть двумерный массив, чётные и нечётные элементы к-рого нужно обрабатывать разными способами. как всё это нормально расписать? ps:делать if'ы на четные-нечётные значения внутри — не вариант.

Program mainCore
use iso_c_binding
integer,parameter::gIDMax=2
integer,parameter::iMax=3
integer::i,j,k
integer*2,target,dimension(1:iMax*2,1:gIDMax)::a=0

#ifdef _OPENMP
write(*,"(a)") "OpenMP is supported!"
#endif

!$OMP PARALLEL DO PRIVATE (i,j,k) COLLAPSE(2)
DO i = 1,gIDMax

DO j=1,iMax*2,2
	a(i,j)=100*i+j
ENDDO

DO k=2,iMax*2,2
	a(i,k)=100*i+k
ENDDO

ENDDO
!$OMP END PARALLEL DO

DO i = 1,gIDMax
DO j=1,iMax*2
	print*,a(i,j)
ENDDO
ENDDO

endProgram mainCore
!gfortran -cpp -fopenmp -Wall -o mainCore.bin mainCore.f95

вот этот код вместо 101 102 103 104 ... , выдаёт 101 0 102 0 ..., т.е. второй внутренний цикл вообще не отрабатывает. как это правильно надо делать? пробовал отделять их через OMP SECTION, но тогда компилятор ругается «not enough DO loops for collapsed !$OMP DO at (1)»

★★★★★

Последнее исправление: thunar (всего исправлений: 1)

В операторе цикла есть третий параметр который означает шаг приращения индекса. Сделай два цикла, один начинается с четного с шагом 2, другой с нечетного с шагом 2, и будет тебе хорошо.

vada ★★★★★
()
Ответ на: комментарий от vada

в тему отвечай — сообщение не читай

thunar ★★★★★
() автор топика

ага, вот так, вроде, заработало

#define TS '--'
Program mainCore
use iso_c_binding
use omp_lib

integer::ThreadID,ThreadsN,i0,gID

integer,parameter::gIDMax=2
integer,parameter::iMax=16
integer*2,target,dimension(1:iMax*2,1:gIDMax)::a=0

#ifdef _OPENMP
write(*,"(a)") "OpenMP is supported!"
#endif

!$omp parallel private(ThreadID,ThreadsN,gID)
ThreadID=OMP_GET_THREAD_NUM()
ThreadsN=OMP_GET_NUM_THREADS()

	!$omp single
	write(*,*)'ThreadsN:',ThreadsN
	!$omp end single

!$omp barrier

	do gID=1,gIDMax
		!$omp do private(i0)
		do i0=1,iMax*2,2
			print*,ThreadId,i0,gID
			a(gID,i0)=100*gID+i0
		endDO
		!$omp end do
		!$omp do private(i0)
		do i0=2,iMax*2,2
			print*,ThreadId,i0,gID
			a(gID,i0)=(100*gID+i0)*(-1)
		endDO
		!$omp end do
	enddo

!$omp barrier

!$omp endparallel

DO i = 1,gIDMax
DO j=1,iMax*2
	print*,a(i,j)
ENDDO
ENDDO

endProgram mainCore
!gfortran -cpp -fopenmp -Wall -o mainCore.bin mainCore.f95
thunar ★★★★★
() автор топика
Ответ на: комментарий от thunar

Что-то мне кажется, что хрень у тебя получилась. Внешний цикл вместо того, чтобы распараллеливаться по итерациям, дублируется по количеству потоков.

Для максимальной параллельности (если уж ты не хочешь использовать if внутри цикла) нужно что-то вроде этого:

!$OMP PARALLEL DO PRIVATE (j,k)
DO i = 1,gIDMax

!$OMP SECTIONS

!$OMP SECTION
!$OMP PARALLEL DO
DO j=1,iMax*2,2
	a(i,j)=100*i+j
ENDDO


!$OMP SECTION
!$OMP PARALLEL DO
DO k=2,iMax*2,2
	a(i,k)=100*i+k
ENDDO

!$OMP END SECTIONS

ENDDO

Код не проверялся.

cdslow ★★
()
Ответ на: комментарий от cdslow

не, всё правильно. по внешним циклам они идут одновременно, на внутренних каждый считает свой кусок. ну да, секшон можно воткнуть.

thunar ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.