Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

OpenMP бағдарламалау технологиясы

Читайте также:
  1. Lt;variant>бір қосымшадан екіншісіне объекті ендіру және байланыстыру арқылы жұмыс істеу технологиясы
  2. БӨЛІМ. ТАМАҚ ӨНІМДЕРІН СУЫҚПЕН ӨҢДЕУ ТЕХНОЛОГИЯСЫ
  3. Введение в технологии параллельного программирования (OpenMP)
  4. НОРМА бағдарламалау жүйесі.

Бүгінгі күні ортақ жадылы компьютерлер үшін ең танымал бағдарламалау құралдарының бірі OpenMP (Open specifications for Multi-Processing) (www.openmp.org). Ол дәстүрлі бағдарламалау тілдеріне және арнайы комментарилерді пайдалануға негізделген. Оның бастауына тізбекті бағдарлама алынады, ал оның параллель нұсқасын құру үшін пайдаланушыға директивтер, функциялар және ортаның айнымалыларының жиыны ұсынылады. Сонымен қатар, құрылатын параллель бағдарлама OpenMP АРI-ді қолдайтын бөлінетін жадылы әртүрлі компьютерлер арасында тасымалданатын болады деп есептеледі.

OpenMP технологиясының өзіндік ерекшелігі, ол пайдаланушыға параллель және тізбекті де орындалу үшін бағдарламаның бір нұсқасын ғана иеленуге мүмкіндік береді. Сонымен қоса мұнда тек параллель режимде дұрыс жұмыс істейтін немесе тізбекті режимде басқа нәтиже беретін бағдарламалар құрастыру мүмкіндігі де қарастырылған.

Стандартты құрастырумен коммерциялық емес ұйым OpenMP ARB (Architecture Review Board) айналысады, және оған SMP-архитектурасын және бағдарламалық қамтамалар құрастыратын ірі компаниялардың өкілдері кіреді (IBM, Intel, Sun, Hewlett – Packard және т.б.). OpenMP дәстүрлі бағдарламалау Fortran, Си/Cи++ тілдерімен жұмыс істей алады. OpenMP спецификациясының бірінші нұсқасы 1997 жылы қазан айында пайда болды, және ол Фортран бағдарламалау тіліне арналған болатын, ал Си/Cи++ тіліне арналған спецификациясы 1998 жылы қазан айында пайда болды. Қазіргі кездегі стандарттың ресми спецификациясы - OpenMP 3,0 (2008 жылы май айында қабылданды).

OpenMP интефейсі SMP-жүйелерінде (SSMP, ccNUMA және т.б.) бағдарламалау үшін стандарт ретінде ойластырылған. OpenMP стандартына компилятор директиваларының, көмекші функциялардың және орта айнымалыларының жиыны спецификациялары кіреді. Стандарт көптеген UNIX-платформаларында және Windows NT ортасында қолжетімділікке ие. Бұл тілдер үшін барлық негізгі конструкциялар ұқсас болғандықтан, OpenMP технологиясы туралы әңгімені бұдан әрі Fortran тіліндегі мысалдар көмегімен жүргіземіз.

Жіптерді (нитей, Pthreads) ұйымдастыру үшін құрылған POSIX-интерфейсі барлық UNIX-жүйелерде қолдау табады және ол алғашында параллельділікті ұйымдастыру мақсаты үшін құрастырылмағанын айта кетейік. OpenMP-ді жоғары деңгейдегі Pthreads (немесе ұқсас жіптер кітапханаларының) жалғасы немесе қондырмасы деп қарастыруға болады. Онда Pthreads-ке жақын терминологиялар мен бағдарламалау модельдері пайдаланылады, мысалы, динамикалық туындайтын жіптер жалпы және бөлінетін деректер синхронизация үшін «құлыптар» механизмі.

POSIX threads терминологиясына сәйкес, кезкелген UNIX-процесс адрестік кеңістіктері ортақ, бірақ командалар ағыны әртүрлі және бөлек стектері болатын бірнеше басқару жіптерінен тұрады. Жіптерді кейбір жағдайларда ағындар, жеңіл процестер, LWP (light-weight processes) деп те атайды.

OpenMP параллель есептеулерді көпағындылық UNIX көмегімен іске асырады, онда «басты» (master) ағын «бағыныңқы» (slave) ағындардың жиынын құрады және есеп солардың арасында таратылады. Ағындар бірнеше процессорлы машиналарда параллель орындалады деп болжанады және онда процессорлар саны ағындар санынан үлкен немесе тең болуы міндетті емес.

Енді ОреnМР ережелері шеңберінде, пайдаланушы өзінің параллель бағдарламасын қалай көрсету керек? Бағдарламаның бар тексті тізбекті және параллель облыстарға бөлінген (44 сурет).

44 сурет. ОреnМР: бағдарламаның орындалу процесі

 

Бастапқы уақыт мезетінде жіп-мастер (нить-мастер) немесе "басты" жіп туындайды және ол бағдарламаның орындалуын стартты нүктеден бастайды. Сонымен қатар ол тек өзі ғана бағдарламаның барлық тізбекті облыстарын орындайды. Параллельділікті қолдау үшін мұнда FORK/JOIN схемасы пайдаланылады. Параллель облысқа енген кезде жіп-мастер қосымша жіптерді туындатады (FORK операциясы орындалады). Одан кейін әрбір қосымша жіп өзінің бірегей нөмірін алады, ал жіп-мастердің нөмірі әрқашан 0. Барлық қосымша туындаған жіптер пареллель облысқа сәйкес келетін бір кодты ғана орындайды. Параллель облыстан шығар мезетте басты жіп қалған жіптердің аяқталуын күтеді және бағдарламаның ары қарай орындалуын өзі ғана жалғастырады (JOIN операциясы орындалады).

Параллель облыста бағдарламаның барлық айнымалылары екі класқа бөлінеді: жалпы (SHARED) және жергілікті (PRIVATE). Жалпы айнымалылар бағдарлама үшін әрқашанда бір экземплярда ғана болып, барлық жіптерге бір атпен ғана қолжетімді болады. Жергілікті айнымалыларды хабарлау әр жіп үшін әрбір айнымалының өз экземплярын туындатады. Жіптің өзінің жергілікті айнымалысының мәнін өзгертуі, басқа жіптердегі дәл осы жергілікті айнымалының мәнінің өзгеруіне ешқандай әсері жоқ. Негізінде, бағдарлама облыстарының соңғы қарастырылған түсініктері және айнымалылар кластары ОреnМР шеңберінде параллель бағдарламалар жазудың жалпы идеяларын анықтайды: бағдарлама текстінің кейбір фрагменттері параллель облыстар болып хабарланады; тек осы облыстар ғана жіптер жиынымен орындалады, ал олар жалпы айнымалылармен де жергілікті айнымалылармен де жұмыс істей алады.

ОреnМР негізгі конструкциясы мен базалық құрылымын қарастырайық [2]. Ондағы барлық директивалар комментарилерде орналасады және келесі комбинациялардың бірінен басталады:!$омр, с$омр немесе *$омр (еске сала кетсек '!', 'с' или '*' символдарының бірінен басталатын жол, Fortran тілінің ережелері бойынша комментарий болып есептеледі).

Бұдан әрі нақты директиваларды суреттеу кезінде жазуды қысқарту үшін, кейбір кездерде біз бұл префикстерді көрсетпейтін боламыз, әрине шын бағдарламаларда олар әрқашан қатысуы қажет.

ОреnМР-ға қатысты барлық функциялар және қоршаған орта айнымалылары омр_ префиксынан басталады.

Параллель облыстарды бейнелеу. Бағдарламадағы параллель облыстарды анықтау үшін директивалардың келесі жұбы пайдаланылады

 

!$ОМР PARALLEL

<бағдарламаның параллель коды>

!$ОМР END PARALLEL

 

Берілген екі директиваның арасына орналасқан параллель кодты орындау үшін, жіп-мастер қосымша omp_num_threads - 1 жіп туғызады, мұндағы omp_num_threads – орта айнымалысы. Оның мәнін пайдаланушы бағдарламаны жүктеудің алдында береді және өзгерте алады. Жіп-мастердің нөмірі әрқашан 0 болатынын жоғарыда айтқанбыз. Барлық жіптер берілген директивалар арасындағы кодты орындайды.

end parallel директивасынан кейін автоматты түрде барлық жіптердің айқын емес синхрондалуы жүреді. Қалай барлық жіптер осы нүктеге жетісімен жіп-мастер бағдараманың келесі бөлігін орындауды жалғастырады, ал қалған жіптер жойылады.

Параллель секциялар бірінің ішінде бірі болуы мүмкін. Арнайы айтылмаса, олар бір жіппен орындалады. Мұндай қабатталып орналасқан секцияларды өңдеуге қажетті стратегияны omp_nested айнымалысы анықтайды, ал олардың мәндерін omp_set_nested функциясының көмегімен өзгертуге болады.

Параллель секцияларда жіптердің санын өзгертуге болады. Егер OMP_DYNAMIC айнымалысының мәні 1-ге тең болса, онда OMP_SET_NUM_THREADS функциясының көмегімен пайдаланушы omp_num_threads айнымалысының мәнін өзгерте алады, олай болса параллель секцияға кірген кездегі туындаған жіптер санын да өзгерте аламыз. OMP_DYNAMIC айнымалысының мәні OMP_SET_DYNAMIC функциясымен бақыланады.

Параллель секция кодының параллель орындалуын және жіптер туындауының қажеттілігін, пайдаланушы if қосымша опциясы көмегімен келесі директивада анықтай алады:

!$ОМР PARALLEL IF(<шарт>)

Егер <шарт> орындалмаса, онда директива қосылмайды, бағдарламаны өңдеу бұрынғы режимде жалғасады.

Жоғарыда, туындаған жіптердің бәрі бір ғана кодты орындайды деп айтылған болатын. Енді олардың арасында жұмысты қалай тиімді түрде бөлуге болады деген сұрақты талқылау керек.

ОрепМР шеңберінде жұмысты бөліп беру үшін келесітөрт нұсқаны пайдалануға болады:

· төменгі деңгейдегі бағдарламалау;

· циклдарды параллель орындау үшін do директивасы;

· бағдарламаның тәуелсіз фрагменттерін параллель орындау үшін sections директивасы;

· код участогын бір рет қана орындау үшін single директивасы.

Төменгі деңгейдегі бағдарламалау OMP_GET_THREAD_NUM және OMP_GET_NUM_THREADS функцияларының көмегімен жұмысты таратуды көздейді, олар сәйкесінше жіп нөмірін және туындаған жіптердің жалпы санын қайтарады. Мысалы, егер келесі түрдегі фрагментті жазсақ:

 

IF(OMP_GET_THREAD_NUM().EQ. 3) THEN

<нөмірі 3 жіп үшін жеке код >

ELSE

<барлық қалған жіптер үшін код >

ENDIF

онда if ... else директивалары арасындағы бағдарлама бөлігі тек 3-ші нөмірлі жіппен ғана, ал else ... endif арасындағы бөлігі – қалған барлығымен орындалады. Бұрынғыша, бастапқы код барлық жіптер үшін бірдей болып қалады. Алайда, ондағы басқарудың нақты берілуі түрлі жіптер үшін әртүрлі жүреді, себебі omp_get_thread_num () функциясы 3 мәнін тек 3-ші нөмірлі жіпке ғана қайтарады.

Егер параллель секцияда цикл операторы кездессе, онда жалпы ережеге сәйкес ол барлық жіптермен орындалады, яғни әрбір жіп бұл циклдің барлық итерацияларын орындайды.

Жіптер арасындағы цикл итерацияларын тарату үшін do директивасын пайдалану керек:

 

!$ОМР DO [опция [[,] опция]...]

<dо-цикл>

[!$ОМР END DO]

 

Бұл директива артынан ілескен do операторы кіретін блокқа қатысты.

· schedule – опциясы жіптер арасында цикл итерацияларын таратудың нақты әдістерін анықтайды.

· static [, m] — итерацияның блокты-циклдық таратылуы. Бірінші жіп m итерациядан тұратын бірінші блокты орындайды, екінші жіп – екінші блокты және т.с.с. соңғы блокқа дейін, одан кейін таратылу қайтадан бірінші жіптен басталады. Егер m–нің мәні көрсетілмесе, онда итерациялардың барлық жиыны, өлшемдері шамамен бірдей болатын үздіксіз бөліктерге (кесектерге) бөлінеді, және олар жіптер арасында таратылады.

· dynamic [,m] - итерациялардың динамикалық таратылуы. Алғашында барлық жіптер m итерациядан тұратын үлестерін (порции) алады, өз жұмыстарын аяқтағаннан кейін әрбір жіп тағы да m итерациядан тұратын келесі үлесін алады. Егер m–нің мәні көрсетілмесе, ол бірге тең деп қабылданады.

· guided [,m] - итерациялардың өлшемдері азаятын блоктармен динамикалық таратылуы. Алғашында белгіленген блоктардың өлшемдері жеткілікті үлкен етіп алынады, ал бағдарламаның жұмыс істеу процесінде ол үнемі біртіндеп азая береді. Итерация блогының минимальді өлшемі m. Алғашқы белгіленген блоктың өлшемі оның іске асырылуына байланысты. Егер m–нің мәні көрсетілмесе, ол бірге тең деп қабылданады.

· runtime – цикл итерацияларының таратылу әдісі бағдарламаның жұмыс істеу кезінде omp_schedule айнымалысының мәніне байланысты таңдалады. Таңдалған әдіс schedule опциясынан кейін жақша ішінде көрсетіледі, мысалы:

!$ОМР DO SCHEDULE (DYNAMIC, 10)

Бұл мысалда, итерациялардың әрбірі 10 итерациядан тұратын блоктар түрінде динамикалық таратылуы пайдаланылады.

Параллель циклдың соңында, параллель жұмыс істейтін жіптердің айқын емес барьерлік синхрондауы іске асады (происходит): олардың ары қарай орындалуы, берілген нүктеге олардың барлығы жеткен кезде ғана жалғасады. Егер мұндай бөгелудің (кідірістің) қажеттілігі болмаса, онда end do nowait аяқтаушы директивасы цикл соңына жеткен жіптерге (қалған жіптермен синхрондалу жасалынбайды) орындауды жалғастыра беруге мүмкіндік береді. Егер end do директивасы айқын түрде көрсетілмесе, онда параллель циклдың соңында синхрондау бәрібір орындалады.

Параллель циклдарды ұйымдастыруға бірнеше табиғи шектеулер қойылады. Дербес жағдайда, дұрыс құрылған бағдарлама қандай жіп параллель циклдің қай итерациясын орындап жатқанына байланысты болмауы керек деп есептеледі. Параллель циклдан қосымша шығуды пайдалануға болмайды. schedule опциясында көрсетілген итерация блогының өлшемі цикл шеңберінде өзгермеуі керек.

Келесі мысалды қарастырайық. Ол бағдарламаның паралель секциясында орналасқан деп есептейік.

 

!$ОМР DO SCHEDULE (STATIC, 2)

DO i = 1, n

DO j = 1, m

A(i, j) = (B(i, j - 1) + B(i - 1, j))/2.0

END DO

END DO

!$OMP END DO

 

Бұл мысалда сыртқы цикл параллель деп хабарланған, және мұнда итерацияның блокты-циклдік таратылуы пайдаланылатын болады (блокта екі итерациядан). Ішкі циклға қатысты ешқандай нұсқаулар жоқ, сондықтан ол әрбір жіппен тізбекті орындалатын болады.

Тәуелсіз фрагменттер деңгейіндегі параллельділік ОреnМР-да sections...end sections қос директиваларының көмегімен, және осы жұптың ішінде орналасқан section директивасының бірнеше санымен беріледі. Мысалы:

 

!$ОМР SECTIONS

!$ОМР SECTION

<фрагмент 1>

!$ОМР SECTION

<фрагмент 2>

!$ОМР SECTION

<фрагмент З>

!$ОМР END SECTIONS

Бұл мысалда, ондағы үш фрагментті параллель орындауға болатындығы көрсетілген. Әрбір фрагмент қандай да бір жіппен тек бір рет қана орындалады. Егер жіптер саны секциялар санынан көп болса, онда қай жіптер қандай секциялар үшін екенін және қандай жіптер қолданылмайтынын авторлардың өздері шешеді. Конструкцияның соңында жіптер жұмысын айқын емес синхрондау қарастырылады. Егер бұндай синхрондаудың қажеттілігі болмаса, онда 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 бірдей сандарының I0 жиыны да болуы мүмкін. Шынында да, I0 процесінен басқа қалған барлық процесті қандай да бір ретпен бірінші оператор орындады деп есептейік. Одан кейін, қандай да бір себепке байланысты олардың орындалуы тоқтатылсын. Осы мезетте I0 нөмірлі процесс I-дің осы мәнін қабылдайды, ал бұл айнымалы жалпы болуы салдарынан, әрбір жіп бірдей мәндерді шығарады. Сондықтан, осындай анықталмағандық болмауы үшін, бағдарламашы әрбір жіптің жалпы айнымалыларды пайдалануын өзі қадағалап отыруы керек.

Бағдарламаның келесі мысалын қарастырайық.

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)

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 конструкциясы пайдаланылғандықтан параллель циклдің соңында жіптердің синхрондалуы болмайды.

Жіптер жұмысын синхрондау үшін ОреnМР тұтас директивалар жиынын пайдаланады. Ең кең таралған және қарапайым синхрондау әдісі - барьер. Ол

!$ОМР BARRIER директивасы көмегімен орындалады. Барлық жіптер осы директиваға жетісімен «тоқтайды», және қалған барлық жіптердің бағдарламаның осы нүктесіне жетуін күтеді, барлығы жетісімен ары қарай жұмыстарын жалғастырады.

Директивалар master...end master жұбы тек қана жіп-мастермен орындалатын код участогын белгілейді. Қалған жіптер бұл участокты елемей өткізіп жібереді де end master директивасынан кейін орналасқан оператордан бастап жұмыстарын жалғастырады. Бұл директива айқын емес синхрондауды ниет етпейді.

Келесі директивалар көмегімен

 

!$ОМР CRITICAL [ (< критикалық секцияның аты>) ]

!$ОМР END CRITICAL [ (<критикалық секцияның аты >) ]

бағдарламаның критикалық секциясы құжатталады. Әрбір уақыт мезетінде критикалық секцияда біреуден артық жіп болмайды. Егер критикалық секция қандай да бір Р0 жіппен орындалып жатса, онда қашан Р0 бұл секцияны орындауын аяқтағанша, осы секция үшін critical директивасын орындаған барлық қалған жіптер бұғатталады. Қалай Р0 жібі end critical директивасын орындайды, солай кірістегі бұғатталған жіптердің бірі секцияға кіреді. Егер критикалық секцияның кірісінде бірнеше жіптер тұрса, онда олардың бірі кездейсоқ түрде алынады, ал қалған бұғатталған жіптер күтулерін жалғастырады. Барлық аталмаған критикалық секциялар шартты түрде бір атпен қаралады, ал бірдей атты иеленетін критикалық секциялар бірегей (бір) секция ретінде қарастырылады.

Жоғарыда келтірілген жіп нөмірін баспалауға қатысты мысалды келесі түрде жетілдіріп қарастырайық:

 

!$ОМР CRITICAL

I = OMP_GET_THREAD_NUM()

PRINT *, I

!$OMP END CRITICAL

 

Бұл жағдайда, егер I айнымалысы жалпы деп хабарланғанның өзінде, бәрібір шығысында міндетті түрде 0 ден omp_num_threads – 1-ге дейінгі барлық сандар пайда болады. Енді, критикалық секция және жалпы айнымалы I пайдаланылатын фрагмент пен критикалық секциясыз жергілікті айнымалыны I пайдаланатын фрагмент арасында қандай айырмашылық бар екенін қарап көрелік. Қазір ғана көргеніміздей нәтиже тек сандардың пайда болу ретінде ғана. Сандар жиыны бірдей болады. Бірақ бұл фрагменттердің орындалуында айтарлықтай айырмашылық бар. Егер критикалық секция бар болса, онда әрбір уақыт мезетінде фрагмент тек қандай да бір жіппен ғана өңделеді. Қалған жіптер, бағдарламаның осы нүктесіне келіп тұрғандарына және жұмысқа дайын болғандарына қарамастан өз кезектерін күтеді. Егер критикалық секция болмаса, онда барлық жіптер бір мезгілде кодтың берілген участогын орындайды. Бір жағынан, критикалық секциялар жалпы айнымалылармен жұмыс істеу үшін ыңғайлы механизм ұсынады. Ал басқа жағынан пайдаланушыға абай болу керек, себебі критикалық секциялар параллель бағдарламаға тізбекті код участкілерін қосады, олар өз кезегінде оның тиімділігін төмендетеді.

Тәжірибе жүзінде критикалық секцияны пайдаланудың дербес жағдайы ретінде жалпы айнымалыларды жаңартуды алуға болады. Мысалы, егер sum айнымалысы жалпы болып және sum = sum + Expr түріндегі оператор бағдарламаның параллель секциясында бар болса, онда берілген операторды бірнеше жіптермен бірмезгілде орындау кезінде дұрыс нәтиже алынбауы мүмкін. Мұндай жағдайларды болдырмау үшін, критикалық секциялар механизмін немесе осындай жағдайлар үшін арнайы қарастырылған atomic директивасын пайдалануға болады:

!$ОМР ATOMIC

SUM = SUM + Expr

atomic директивасы өзінен кейінгі тұрған операторға ғана қатысты. Бұл мысалда ол SUM жалпы айнымалысымен дұрыс жұмыс істеуге кепілдік береді.

Заманауи параллель есептеу жүйелерінде күрделі құрылым және жады иерархиясы пайдаланылуы мүмкін болғандықтан, пайдаланушының өзіне қажетті уақыт мезеттерінде, әрбір жіп жадының бірегей үйлестірілген бейнесін көре алатынына кепілдігі болуы керек.

!$ОМР FLUSH [ айнымалылар_тізімі ]

Бұл директиваның орындалу барысында, регистрлерде уақытша сақталынған барлық айнымалылардың мәндері негізгі жадыға енгізіледі, жіптердің жұмыс істеу барысында айнымалыларға жасаған өзгертулері қалған жіптерге көрінетін болады, егер қандай да бір ақпарат шығыс буферлерінде сақталынса, олар алынып тасталады. Берілген директиваның толық көлемде орындалуы айтарлықтай қосымша шығындарға алып келетіндіктен, қандай да бір уақыт мезетінде барлығы емес ал жекелеген айнымалылардың ғана үйлесімділігін көрсетудің кепілдігі керек болған жағдайда, бұл айнымалыларды айқын түрде тізіп көрсету қажет. Біз бұл бөлімде ОреnМР технологиясының конструкцияларына толық талдау жүргізбейміз. Fortran, С және C++ тілдері үшін ОреnМР туралы толық текстерді http://www.openmp.org сайтынан ала аласыздар. Сонымен қатар, жоғарыда келтірілген және басқа да көптеген мысалдардың Fortran, С және C++ тілдеріне арналып жасалған толық нұсқаларын А.С.Антоновтың «Параллельное программирование с использованием технологии OpenMP» атты оқу құралынан кездестіре аламыз. ОреnМР технологиясының директивалары, функциялары, опциялары және орта айнымалылары қосымша 2-де берілген.

Сонымен, ОреnМР технологиясы несімен тартымды және қызықты? Бірнеше моменттерінің ішінен екеуін арнайы айта кетуге болады. Біріншіден, ОреnМР технологиясы алғашында пайдаланушы параллель және тізбекті бағдарламалар үшін бір текспен ғана жұмыс істей алатындай етіп жобаланған. Тізбекті машинада дәстүрлі компилятор ОреnМР директиваларын жай "байқамай" қалады, себебі олар комментарилерде орналасқан. Туындайтын мәселелердің бір ғана бастауы орта айнымалылары және арнайы функциялар болуы мүмкін. Алайда, олар үшін тізбекті жағдайда ОреnМР-бағдарламасының дұрыс жұмысына кепілдік беретін стандарт спецификацияларында арнайы "бұқтырмалар" ("заглушки") қарастырылған. Ол үшін тек бағдарламаны қайта компиляция жасап, басқа кітапхананы қосу керек.

ОреnМР технологиясының келесі артықшылығы бағдарламаны біртіндеп "инкрементті" параллельдеу мүмкіндігі. Негізіне тізбекті кодты ала отырып, пайдаланушы әр қадам сайын жаңа параллель конструкцияларды бейнелейтін жаңа директиваларды қосып отырады. Мұнда бірден тұтас параллель бағдарламаны құрудың қажеттілігі жоқ, оны құру тізбекті түрде жүргізіледі. Бұл өз кезегінде бағдарламалау процесін де жөндеуді де ықшамдауға мүмкіндік береді.

 


Дата добавления: 2015-10-29; просмотров: 698 | Нарушение авторских прав


Читайте в этой же книге: М. Флин (M. Flynn) классификациясы. | Жедел жады құрылымы | Функционалдық құрылғылар | Ортақ жадылы параллель компьютерлер | Таратылған жадылы есептеу жүйелері | Кластерлік жүйелер | Кластерлерді тұрғызудың коммуникациялық технологиялары | Шексіз параллелділік концепциясы | Бекітілім 1.2.3 | Ішкі параллельділік |
<== предыдущая страница | следующая страница ==>
Дәстүрлі тізбекті тілдерді пайдалану.| INTEGER SCOUNT, STYPE, RCOUNT, RTYPE, ROOT, COMM, IERR

mybiblioteka.su - 2015-2024 год. (0.029 сек.)