139
мүмкін. Бұл жағдайда, бағдарламаның масштабталуы туралы ойды ұмытуға
тура келеді.
Кӛрсетілген есептер шынында да ӛте күрделі. Бірнеше нақты мысал
қарастырғаннан кейін, әркімнің де оған кӛзі жетері анық.
Енді аталған ситуацияны шамалы ықшамдап кӛрейік және ортақ жадылы
параллель компьютерлерді қарастырайық. Мұнда тек бағдарламаның
параллельдігін анықтау есебі ғана қалатындай болып кӛрінеді,
бірақ бәрі
сонымен шектеле ме? Бағдарламаның үш жолдан ғана тұратын келесі
фрагментін қарастырайық:
DO 10 i = 1, n
DO 10 j = 1, n
10
U(i + j) = U(2*n - i - j + 1 ) * q + p
Берілген циклді конструкцияның қандай итерациялары ӛзара тәуелсіз
болады және фрагментті параллель орындауға болады ма? Фрагменттің
ақпараттық құрылымы n = 10 жағдайы үшін 43-ші суретінде кӛрсетілген.
45 сурет. Фрагменттің ақпараттық құрылымы, n = 10.
Суреттен циклдардың параллель еместігін бірден анықтауға болады.
Алайда берілген фрагменттің ішкі екі циклдары параллель болатындай етіп
түрлендіруге болатыны байқалады.
DO 10 i = 1, n
DO 20 j = 1, n - i
20 U(i + j) = U(2*n - i - j + l)*q + p
DO 30 j = n - i + 1, n
140
30 U(i + j) = U(2*n - i - j + l)*q + p
10 continue .
Егер берілген фрагментті (n = 1000) векторлы-конвейерлік Cray С90
компьютерінде (шектік ӛнімділігі 1 Гфлопс) орындаса, онда оның ӛнімділігі
20 Мфлопс құрайды [10]. Тӛмен ӛнімділіктің негізгі себебі, компилятор, ішкі
циклдарының барлық итерациялары ӛзара тәуелсіз болатын фрагменттің
эквивалентті формасын ӛз бетінше таба алмауында,
яғни ол фрагментті
векторлай алмайды. Сонымен қатар ӛзгертілген фрагментте, дәл осы
компьютердің ӛнімділігі шамамен 420 Мфлопс құрайтынын кӛреміз. Бұдан
шығатын қорытынды, фрагмент бар болғаны үш жолдан тұрғанымен ондағы
параллельділікті анықтау оңай бола бермейді.
Енді келесі фрагментті қарастырайық:
DO 10 i = 1, n
10
U(i) = Func(U, i)
мұндағы Func – пайдаланушы функциясы. «Цикл итерациялары ӛзара
тәуелсіз бе, әлде жоқ па» деген сұраққа жауап беру үшін, компилятор Func
функциясы U массив элементтерін пайдалана ма, жоқ па екенін анықтап алу
керек. Егер функция денесінің қандай да бір жерінде, мысалы U(i-1) элементі
орындалатын болса, онда итерациялар тәуелді болғаны. Егер Func
функциясының ӛзі айқын түрде U массивін пайдаланбаса, бірақ оның
денесінің қандай да бір жерінде басқа функцияны шақыру тұрса және ол ӛз
кезегінде U(i-1)
элементін пайдаланатын болса, онда цикл итерациялары
тағы да тәуелді болғаны. Жалпы жағдайда, компилятор еркін ұзындықты
шақырулар тізбегіне талдау жасай білуі және толық процедура-аралық
талдауды орындай алуы керек. Жекелеген жағдайларда бұны істеуге болады,
ал жалпы бұл есеп ӛте күрделі десе болады.
Ал енді компилятор, келесі фрагменттің итерацияларының тәуелсіздігі
туралы қандай қорытынды жасауы мүмкін:
DO 10 i = 1, n
10
U(i) = A(i) + U ( I U ( i ) )
Егер IU массиві элементтерінің мәндері
туралы ешқандай жорамал
ақпараттар жоқ болса, ал ол кӛбіне болмайды, онда анық ештеңе айта
алмаймыз. Параллель іске асыру нәтиженің ӛзгеруіне алып келуі мүмкін,
сондықтан «сенімділік» үшін компилятор тізбекті кодты генерация жасайды.
141
Компилятор нашар ма? Әрине жоқ, тек дәл осы жағдайда ол ештеңе де істей
алмайды. Осыған ұқсас, фрагменттің шынайы құрылымын анықтау
компиляторға күрделі болатын, олай болса тиімді параллель іске асыру да
күрделі болатын мысалдарды кӛптеп келтіруге болады.
Туындайтын
мәселелерді шешу қабілеті тӛмен деп әрине компиляторды кіналап қажеті
жоқ. Практика емес теория жүзінде де бағдарламалау тілінің
заңдылықтарына сәйкес жазылған еркін фрагментті толықтай талдаудан
ӛткізу мүмкін емес. Егер компьютерлердің архитектурасы күрделі болмаса,
онда компиляторлар дәстүрлі тізбекті бағдарламалардан да тиімді кодтарды
генерациялауға толық жағдайлары бар. Кері жағдайда компиляторға
бағдарламаның қайсібір қасиеттеріне сілтеме жасайтын «жӛн сілтеулер»
қажет.
Компиляторға жӛн сілтеулер әртүрлі формада ӛрнектелуі мүмкін. Бір
жағдайларда
комментарийлермен
жазылған
арнайы
директивалар
пайдаланылады, келесі бір жағдайларда тілге жаңа конструкциялар енгізіледі,
кӛбіне қосымша қызметтік функциялар пайдаланылады. Типтік байланыс:
дәстүрлі тізбекті тіл + қарастырылған тәсілдердің қандай да бір
комбинациясы.
Бағдарлама
текстіне
комментариилерімен
арнайы
директиваларды пайдалануға негізделген параллель компьютерлермен жұмыс
істеуге арналған ең танымал Fortran тілінің кеңейтілімінің бірі - High
Performance Fortran (HPF). Ӛткен ғасырдың 90-шы
жылдарының ортасында
HPF-ке үлкен үміт артылған болатын, ӛйткені бұл тіл бірден
тасымалданатын
параллель бағдарламаларды құрастыруға бағытталған болатын. HPF пайда
болу уақыты компьютерлердің массалық параллельдігінің даму периодымен
дәл келіп, ол кезде бағдарламалардың тасымалдану мәселесі ӛте ӛзекті мәселе
болды. Алайда бұл жол қабылданбады, себебі HPF конструкциясының
күрделілігі оны тиімді компиляторларды құру жолындағы алынбас қамалға
айналдырды десе болады.
Достарыңызбен бөлісу: