Тәуелсіз
фрагменттер
деңгейіндегі
параллельділік
ОреnМР-да
SECTIONS
...
END SECTIONS
қос директиваларының кӛмегімен, және осы
жұптың ішінде орналасқан
SECTION
директивасының бірнеше санымен
беріледі. Мысалы:
!$ОМР SECTIONS
!$ОМР SECTION
<фрагмент 1>
!$ОМР SECTION
<фрагмент 2>
!$ОМР SECTION
<фрагмент З>
!$ОМР END SECTIONS
Бұл мысалда, ондағы үш фрагментті параллель орындауға
болатындығы кӛрсетілген. Әрбір фрагмент қандай да бір жіппен тек бір рет
қана орындалады. Егер жіптер саны секциялар санынан кӛп болса, онда қай
жіптер
қандай
секциялар
үшін
екенін
және
қандай
жіптер
қолданылмайтынын авторлардың ӛздері шешеді. Конструкцияның соңында
жіптер жұмысын айқын емес синхрондау қарастырылады. Егер бұндай
148
синхрондаудың қажеттілігі болмаса, онда END SECTIONS
NOWAIT
директивасын пайдалануға болады.
DO
және
SECTIONS
директиваларында
FIRSTPRIVATE
және
LASTPRIVATE
опцияларын ӛз айнымалыларының тізімімен пайдалануға
болады. Бұл опциялар берілген конструкцияларға кірер алдында, жергілікті
айнамалыларды инициалдауды басқарады, сонымен қатар параллель цикл
және секция ӛңделуі аяқталғаннан кейінгі айнымалылардың мәндерін
анықтайды.
Егер параллель секцияда кодтың қандай да бір бөлігі тек бір рет қана
орындалуы
керек
болса,
онда
оны
SINGLE
...
END
SINGLE
директиваларының арасына орналастыру керек. Мұндай қажеттілік кӛбіне
жалпы айнымалылармен жұмыс істегенде жиі пайда болады. Айтылған
участок бір жіппен ғана орындалады. Егер соңында
END SINGLE NOWAIT
директивасы кӛрсетілмесе, онда барлық жіптердің айқын емес синхрондалуы
орындалады.
ОреnМР базалық түсініктерінің бірі – айнымалылар кластары.
Параллель облыста пайдаланылатын барлық айнымалылары не жалпы
немесе
жергілікті
болуы
мүмкін.
Жалпы
айнымалылар
SHARED
директивасымен сипатталады, ал жергілікті – PRIVATE директивасымен.
Әрбір жалпы айнымалы бағдарлама үшін әрқашанда бір экземплярда ғана
болып, әрбір жіпке бір атпен ғана қолжетімді болады. Әрбір жергілікті
айнымалы үшін әрбір жіпте, осы жіпке ғана қолжетімді болатын осы
айнымалының жеке экземпляры бар болады.
Келесі фрагмент параллель секцияда орналасқан деп есептейік:
I = OMP_GET_THREAD_NUM()
PRINT *, I
Егер I айнымалысы берілген параллель секцияда жергілікті деп хабарланса,
онда шығысында 0 ден
OMP
_
NUM
_
THREADS
– 1-
ге дейінгі сандар жиыны
алынады. Жалпы айтқанда сандар еркін ретпен алынады, бірақ әрбір сан тек
бір рет қана кездеседі. Егер I айнымалысы берілген параллель секцияда
жалпы деп хабарланса, онда шығысында 0 ден
OMP
_
NUM
_
THREADS
– 1
аралығында жататын
OMP
_
NUM
_
THREADS
сандар тізбегі алынады. Бұл
жағдайда, тізбекте қанша және қандай сандар болатыны туралы алдын-ала
ештеңе айтуға болмайды. Дербес жағдайда
OMP
_
NUM
_
THREADS
бірдей
сандарының
I
0
жиыны да болуы мүмкін. Шынында да, I
0
процесінен басқа
қалған барлық процесті қандай да бір ретпен бірінші оператор орындады деп
есептейік. Одан кейін, қандай да бір себепке байланысты олардың
орындалуы тоқтатылсын. Осы мезетте I
0
нӛмірлі процесс I-дің осы мәнін
қабылдайды, ал бұл айнымалы жалпы болуы салдарынан, әрбір жіп бірдей
мәндерді шығарады. Сондықтан, осындай анықталмағандық болмауы үшін,
149
бағдарламашы әрбір жіптің жалпы айнымалыларды пайдалануын ӛзі
қадағалап отыруы керек.
Бағдарламаның келесі мысалын қарастырайық.
PROGRAM HELLO
INTEGER NTHREADS, TID,
OMP_GET_NUM_THREADS,
+OMP_GET_THREAD_NUM
С жіптердің жергілікті айнымалылармен туындауы
!$ОМР PARALLEL PRIVATE(NTHREADS, TID)
С өз нөмірін алу және баспаға шыығару
TID = OMP_GET_THREAD_NUM()
PRINT *, 'Hello World from thread =
', TID
С Жіп-мастер үшін код участогы
IF (TID .EQ. 0) THEN
NTHREADS = OMP_GET_NUM_THREADS()
PRINT *, 'Number of threads = ', NTHREADS
ENDIF
С Параллель секцияның аяқталуы
!$ОМР END PARALLEL
END
Әрбір жіп параллель секцияны кӛрсететін код фрагментін орындайды,
және жіп нӛмірімен құттықтау сӛзді «Hello World from thread = жіп
нөмірі» баспаға береді. Қосымша, жіп-мастер туындаған жіптердің жалпы
санын баспаға шығарады. Параллель секция хабарламасында
NTHREADS
және
TID
айнымалыларының жергілікті екені айқын кӛрсетілген. Жіптердің
жалпы санын және олардың нӛмірлерін анықтау үшін кітапханалық
функциялар
OMP
_
GET
_
NUM
_
THREADS
және
OMP
_
GET
_
THREAD
_
NUM
пайдаланылған.
Векторларды қосу бағдарламасын қарастырайық.
PROGRAM VEC_ADD_DO
INTEGER N, CHUNK, I
PARAMETER (N = 1000)
150
PARAMETER (CHUNK =100)
REAL A(N), B(N), C(N)
! массивтерді инициализациялау
DO I = 1,N
A(I) = I * 1.0
B(I) = A(I)
END DO
!$OMP PARALLEL SHARED(A,B,C,N)
PRIVATE(I) !$OMP DO
SCHEDULE(DYNAMIC,CHUNK)
DO I = 1, N
C(I) = A(I) + B(I)
END DO
!$OMP END DO NOWAIT
!$OMP END PARALLEL
END
Берілген мысалда А,
В, С массивтері және
N
айнымалысы жалпы, ал I
айнымалысы жергілікті деп хабарланған. I айнымалысы жергілікті
болғандықтан, әрбір процесс бұл айнымалының ӛз кӛшірмесін алады.
Параллель цикл итерациялары жіптер арасында динамикалық таратылады.
Блоктар ӛлшемі бекітілген және тең CHUNK. NOWAIT конструкциясы
пайдаланылғандықтан параллель циклдің соңында жіптердің синхрондалуы
болмайды.
Достарыңызбен бөлісу: |