Концепцията за паралелно изчисление е обща организационна схема. Паралелно изчисление в WinNT. Методи за синхронизиране на паралелно взаимодействие

Паралелно изчисление – начин на организиране компютърни изчисления, в който програмите се разработват като набор от взаимодействащи изчислителни процеси, изпълнявани едновременно.

има различни начинивнедряване на паралелни изчисления: всеки изчислителен процес може да бъде реализиран като процес на операционна система или изчислителните процеси могат да бъдат набор от нишки за изпълнение в рамките на един процес. Нишка (или по-правилно нишка за изпълнение) е най-малката единица за обработка, чието изпълнение може да бъде зададено от ядрото на операционната система. Множество нишки за изпълнение могат да съществуват в рамките на един и същи процес и да споделят ресурси като памет, докато процесите не споделят тези ресурси. Паралелните програми могат да се изпълняват физически или последователно на един процесор - редувайки последователно стъпките на всеки изчислителен процес, или паралелно - разпределяйки един или повече процесори (разположени наблизо или разпределени в компютърна мрежа) за всеки изчислителен процес.

Основната трудност при проектирането на паралелни програми е да се осигури правилната последователност от взаимодействия между различни изчислителни процеси, както и споделянето на ресурси като напр. RAMили периферни устройства.

В някои системи за паралелно програмиране прехвърлянето на данни между компонентите е скрито от програмиста, докато в други трябва да се посочи изрично. Явните взаимодействия могат да бъдат разделени на два типа:

1. Взаимодействие чрез споделена памет (например в Java или C#). Този типпаралелното програмиране обикновено изисква някаква форма на улавяне на управление за координиране на нишки помежду си.

2. Взаимодействие чрез предаване на съобщения. Съобщенията могат да се обменят асинхронно или с помощта на метода рандеву, при който подателят се блокира, докато съобщението му не бъде доставено. Асинхронното предаване на съобщения може да бъде надеждно (с гаранция за доставка) или ненадеждно. Паралелните системи за предаване на съобщения често са по-лесни за разбиране от системите със споделена памет и обикновено се считат за по-добър метод за паралелно програмиране. Съобщенията могат да бъдат ефективно реализирани на симетрични мултипроцесори със или без споделена кохерентна памет.

Има доста различни технологиипаралелно програмиране. Освен това тези технологии се различават не толкова в езиците за програмиране, колкото в архитектурните подходи за изграждане на паралелни системи. Например, някои технологии включват изграждането на паралелни решения, базирани на няколко компютъра (както един, така и различни видове), други предлагат работа на една машина с няколко процесорни ядра. В момента основният софтуерни инструментисъздаване на паралелни програми са:

1. OpenMPизползвани в паралелни системи със споделена памет (напр. модерни компютрис многоядрени процесори);

2. MPI (интерфейс за предаване на съобщения)е стандарт за системи за пренос на съобщения между паралелно изпълняващи се процеси, използван при разработването на програми за суперкомпютри;

3. POSIX нишкие стандарт за изпълнение на нишки за изпълнение;

4. Операционна зала Windows системаима вградена поддръжка за многонишкови приложения за C++ на ниво API;

5. PVM (паралелен Виртуална машина) ви позволява да комбинирате разнородни компютри, свързани в мрежа, в общ изчислителен ресурс.

Системите, базирани на няколко компютъра, се класифицират като системи за разпределени изчисления. Такива решения се използват от доста време. Най-яркият пример за разпределена изчислителна технология е MPI (интерфейс за предаване на съобщения). MPI е най-разпространеният стандарт за интерфейс за обмен на данни за паралелно програмиране; има реализации за огромен брой компютърни платформи. MPI предоставя на програмиста унифициран механизъм за взаимодействие на клоновете вътре паралелно приложениенезависимо от архитектурата на машината (еднопроцесорен/мултипроцесорен със споделена/отделна памет), относително разположение на разклоненията (на един и същи процесор или на различни).

Тъй като MPI е предназначен основно за системи със споделена памет, използването му за организиране на паралелен процес в система с споделена памет е изключително трудно и непрактично. Все пак нищо не ви пречи да правите MPI решения за една машина.

Но системите за паралелно програмиране за работа на една машина започнаха да се развиват сравнително наскоро. Разбира се, това не са принципно нови идеи, но това беше с появата на многоядрени системи на пазара персонални компютри, мобилни устройства, технологии като OpenMP получиха значително развитие.

Много е важно технологията за паралелно програмиране да поддържа способността постепенно да се прави паралелна програма. Разбира се, една идеална паралелна програма трябва веднага да бъде написана паралелно, може би на някакъв функционален език, където въпросът за паралелизиране изобщо не възниква. Но на практика е необходимо постепенно да се паралелизира писмената последователна, за да се увеличи производителността. В този случай технологията OpenMP ще бъде много добър избор. Тя ви позволява да изберете местата в приложението, които най-много се нуждаят от паралелизиране, и първо да ги направите паралелни. Процесът на разработване на паралелни версии може да бъде прекъснат, междинните версии на програмата освободени и върнати при необходимост. Ето защо технологията OpenMP стана доста популярна.

OpenMP (Open Multi-Processing) е набор от директиви за компилатор, библиотечни процедури и променливи на средата, които са предназначени за програмиране на многонишкови приложения на многопроцесорни системи със споделена памет.

Спецификацията OpenMP се разработва от няколко големи производители. компютърни технологиии софтуер, чиято работа се регулира от организация с нестопанска цел, наречена OpenMP Architecture Review Board (ARB).

Първата версия се появи през 1997 г., предназначена за езика Fortran. Версията C/C++ е разработена през 1998 г. През 2008 г. беше пуснат OpenMP 3.0. Интерфейсът OpenMP се превърна в една от най-популярните технологии за паралелно програмиране. OpenMP се използва успешно както при програмирането на суперкомпютърни системи с голям брой процесори, така и в настолни потребителски системи или, например, в Xbox 360.

OpenMP прилага паралелно изчислениеизползване на многопоточност, при която „главната“ нишка създава набор от подчинени (подчинени) нишки и задачата се разпределя между тях. Приема се, че нишките се изпълняват паралелно на машина с множество процесори (не е необходимо броят на процесорите да е по-голям или равен на броя на нишките).

Задачите, изпълнявани от нишки паралелно, както и данните, необходими за изпълнението на тези задачи, се описват с помощта на специални предпроцесорни директиви на съответния език - прагми. Например, част от код на Fortran, която трябва да бъде изпълнена от няколко нишки, всяка от които има собствено копие на променливата N, се предхожда от следната директива: !$OMP PARALLEL PRIVATE(N)

Броят на създадените нишки може да се регулира както от самата програма чрез извикване на библиотечни процедури, така и външно, като се използват променливи на средата.

Ключовите елементи на OpenMP са

1. конструкции за създаване на нишки (паралелна директива);

2. конструкции за разпределяне на работата между нишките (директиви DO/for и section);

3. конструкции за управление на работа с данни (споделени и частни изрази за дефиниране на клас памет от променливи);

4. конструкции за синхронизиране на нишки (критични, атомни и бариерни директиви);

5. библиотечни процедури за поддръжка по време на изпълнение (например omp_get_thread_num);

6. променливи на средата (например OMP_NUM_THREADS).

OpenMP използва модел за паралелно изпълнение с разклоняване и сливане. OpenMP програма започва като единична нишка за изпълнение, наречена начална нишка. Когато една нишка срещне паралелна конструкция, тя създава нова група нишки, състояща се от себе си и няколко допълнителни нишки, и става главен на новата група. Всички членове на новата група (включително основната) изпълняват код вътре в паралелната конструкция. В края на паралелната структура има имплицитна бариера. След паралелната конструкция само основната нишка продължава да изпълнява потребителския код. Паралелен регион може да бъде вложен с други паралелни региони, в които всяка нишка от оригиналния регион става основна нишка за своята група нишки. Вложените региони могат от своя страна да включват региони на по-дълбоко ниво на влагане.

Броят на нишките в група, работещи паралелно, може да се контролира по няколко начина. Един от тях е да използвате променлива на средата OMP_NUM_THREADS. Друг начин е да извикате процедурата omp_set_num_threads(). Друг начин е да използвате израза num_threads в комбинация с паралелната директива.

В тази програма два масива (a и b) се добавят паралелно от десет нишки.

#включи

#включи

int main(int argc, char *argv)

float a[N], b[N], c[N];

omp_set_dynamic(0); // не позволява на библиотеката openmp да променя броя на нишките по време на изпълнение

omp_set_num_threads(10); // задайте броя на нишките на 10

// инициализиране на масивите

за (I = 0; I< N; i++)

// изчисляваме сумата на масивите

#pragma omp parallel shared(a, b, c) private(i)

за (I = 0; I< N; i++)

c[i] = a[i] + b[i];

printf("%f\n", c);

Тази програма може да бъде компилирана с помощта на gcc-4.4 и по-късно с флага –fopenmp. Очевидно, ако премахнете включването на заглавния файл omp.h, както и извикванията на конфигурационната функция на OpenMP, програмата може да бъде компилирана на всеки C компилатор като обикновена последователна програма.

OpenMP се поддържа от много съвременни компилатори:

1. Компилаторите на Sun Studio поддържат официалната спецификация - OpenMP 2.5 - с подобрена производителност под Solaris OS; Linux поддръжкапланирано за следващото издание.

2. Visual C++ 2005 и по-нови версии поддържат OpenMP в изданията Professional и Team System.

3. GCC 4.2 поддържа OpenMP, а някои дистрибуции (като Fedora Core 5 gcc) са включили поддръжка в своите версии на GCC 4.1.

4. Intel C++ Compiler, включително версия на Intel Cluster OpenMP за програмиране в системи с разпределена памет.

Интерфейс за предаване на съобщения (MPIинтерфейс за предаване на съобщения) е програмен интерфейс за пренос на информация (API), който позволява обмен на съобщения между процеси, изпълняващи една и съща задача. Разработено от William Group, Evin Lusk и други.

MPI е най-често срещаният стандарт за интерфейс за обмен на данни за паралелно програмиране и има реализации за голям брой компютърни платформи. Използва се при разработване на програми за клъстери и суперкомпютри. Основното средство за комуникация между процесите в MPI е предаването на съобщения един към друг. MPI стандартизацията се извършва от MPI Forum. Стандартът MPI описва интерфейс за предаване на съобщения, който трябва да се поддържа както на платформата, така и в потребителските приложения. В момента съществува голям бройбезплатни и комерсиални реализации на MPI. Има реализации за езиците Fortran 77/90, C и C++.

MPI е фокусиран предимно върху системи с разпределена памет, тоест когато разходите за трансфер на данни са високи, докато OpenMP е фокусиран върху системи със споделена памет (многоядрени със споделен ESH). И двете технологии могат да се използват заедно за оптимално използване на многоядрени системи в клъстер.

Първата версия на MPI е разработена през 1993-1994 г., а MPI 1 е пусната през 1994 г.

Повечето съвременни реализации на MPI поддържат версия 1.1. Стандартната MPI версия 2.0 се поддържа от повечето съвременни реализации, но някои функции може да не са напълно внедрени.

изпращане и получаване на съобщения между отделни процеси;

колективни взаимодействия на процеси;

взаимодействия в процесни групи;

внедряване на топологии на процеси;

генериране на динамични процеси и управление на процеси;

еднопосочни комуникации (Get/Put);

паралелен вход и изход;

разширени колективни операции (процесите могат да изпълняват колективни операции не само в рамките на един комуникатор, но и в рамките на няколко комуникатора).

Версия MPI 2.1 беше пусната в началото на септември 2008 г.

Основният механизъм за комуникация между MPI процесите е предаването и приемането на съобщения. Съобщението съдържа предадени данни и информация, която позволява на получаващата страна да ги получи избирателно:

1. подател - ранг (номер в групата) на подателя на съобщението;

2. получател - ранг на получателя;

3. знак - може да се използва за разделяне различни видовесъобщения;

4. комуникатор - групов код на процес.

Операциите по приемане и предаване могат да бъдат блокиращи или неблокиращи. За неблокиращи операции са дефинирани функции за проверка на готовността и изчакване за завършване на операцията.

Друг метод за комуникация е отдалечен достъп до паметта (RMA), който позволява областта на паметта на отдалечен процес да бъде прочетена и модифицирана. Локален процес може да прехвърли областта на паметта на отдалечен процес (в рамките на прозорец, определен от процесите) в неговата памет и обратно, а също така да комбинира данни, прехвърлени към отдалечения процес, с данни, налични в неговата памет (например чрез сумиране ). Всички операции отдалечен достъпкъм паметта не блокират, но блокиращите функции за синхронизация трябва да бъдат извикани преди и след тяхното изпълнение.

По-долу е примерна програма за изчисляване на π в C с помощта на MPI:

// Свързване на необходимите заглавки

#включи

#включи

// Включва MPI заглавен файл

#включете "mpi.h"

// Функция за междинни изчисления

двойно f (двойно a)

връщане (4.0 / (1.0+ a*a));

// Основна функция на програмата

int main(int argc, char **argv)

// Деклариране на променливи

int done = 0, n, myid, numprocs, I;

двойно PI25DT = 3.141592653589793238462643;

двойно mypi, pi, h, сума, x;

двойно начално време = 0.0, крайно време;

char име_на_процесор;

// Инициализиране на MPI подсистемата

MPI_Init(&argc, &argv);

// Вземете размера на комуникатора MPI_COMM_WORLD

// (общ брой процеси в рамките на задачата)

MPI_Comm_size(MPI_COMM_WORLD,&numprocs);

// Вземете номера на текущия процес в рамките

// комуникатор MPI_COMM_WORLD

MPI_Comm_rank(MPI_COMM_WORLD,&myid);

MPI_Get_processor_name(processor_name,&namelen);

// Показване на номера на нишката в споделения пул

fprintf(stdout, “Процес %d от %d е на %s\n”, myid,numprocs,processor_name);

// брой интервали

fprintf(stdout, „Въведете броя на интервалите: (0 излиза)“);

if(scanf(“%d”,&n) != 1)

fprintf(stdout, „Няма въведен номер; излизане\n“);

MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

h = 1,0 / (двойно)n;

// Изчисляване на точката, присвоена на процеса

for(I = myid + 1 ; (I<= n) ; I += numprocs)

x = h * ((двойно)I – 0,5);

// Нулирайте резултатите от всички процеси и добавете

MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

// Ако това е основният процес, изведете резултата

printf(“PI е приблизително %.16f, грешката е %.16f\n”, pi, fabs(pi – PI25DT));

endwtime = MPI_Wtime();

printf(“време на стенния часовник = %f\n”, endwtime-startwtime);

// Освобождаване на MPI подсистемата

Най-често срещаните реализации на MPI днес са:

MPICH е най-често срещаната безплатна реализация, работи на UNIX системи и Windows NT

LAM/MPI е друга безплатна реализация на MPI. Поддържа хетерогенни конфигурации, LAM (http://www.lam-mpi.org) поддържа хетерогенни конфигурации, пакет Globus и отговаря на IMPI (Interoperable MPI).

Поддържат се различни комуникационни системи (включително Myrinet).

WMPI - реализация на MPI за Windows

MPI/PRO за Windows NT - търговска реализация за Windows NT

Intel MPI - търговска реализация за Windows/Linux

Microsoft MPI е включен в Compute Cluster Pack SDK. Базиран на MPICH2, но включва допълнителни възможности за управление на задачи. Поддържа се спецификация MPI-2.

HP-MPI - търговска реализация от HP

SGI MPT - платена MPI библиотека от SGI

Mvapich - безплатна реализация на MPI за Infiniband

Open MPI - безплатно изпълнение на MPI, наследник на LAM/MPI

Oracle HPC ClusterTools - безплатно внедряване за Solaris SPARC/x86 и Linux, базирано на Open MPI

MPJ - MPI за Java

POSIX нишки- POSIX стандарт за прилагане на нишки за изпълнение, дефиниране на API за тяхното създаване и управление.

Библиотеките, които прилагат този стандарт (и функциите на този стандарт), обикновено се наричат ​​Pthreads (функциите имат префикс "pthread_"). Въпреки че най-известните опции са за Unix-подобни операционни системи като Linux или Solaris, има и реализация за Microsoft Windows (Pthreads-w32)

Pthreads дефинира набор от типове и функции в езика за програмиране C. Заглавният файл е pthread.h.

Типове данни:

1. pthread_t – дескриптор на нишка;

2. pthread_attr_t – списък с атрибути на нишка.

Функции за контрол на нишката:

1. pthread_create() – създаване на нишка;

2. pthread_exit() – прекратяване на нишката (трябва да се извика от функцията на нишката при прекратяване);

3. pthread_cancel() – анулира нишката;

4. pthread_join() – блокира изпълнението на нишка, докато друга нишка, посочена в извикването на функцията, прекрати;

5. pthread_detach() – освобождаване на ресурсите, заети от нишката (ако нишката работи, ресурсите ще бъдат освободени след нейното приключване);

6. pthread_attr_init() – инициализиране на атрибутната структура на нишката;

7. pthread_attr_setdetachstate() – указва на системата, че след прекратяване на нишката може автоматично да освободи ресурсите, заети от нишката;

8. pthread_attr_destroy() – освобождава памет от атрибутната структура на нишката (унищожава дескриптора).

Функции за синхронизиране на нишки:

2. pthread_mutex_init(), pthread_mutex_destroy(), pthread_mutex_lock(), pthread_mutex_trylock(), pthread_mutex_unlock();

3. pthread_cond_init(), pthread_cond_signal(), pthread_cond_wait().

Пример за използване на нишки в C:

#включи

#включи

#включи

#включи

статичен void wait_thread(void)

време_t начало_време = време(NULL);

докато (време(NULL) == начално_време)

/* не правете нищо, освен да дъвчете CPU парчета за до една секунда. */

статичен void *thread_func(void *vptr_args)

за (I = 0; I< 20; i++)

fputs("b\n", stderr);

pthread_t нишка;

if (pthread_create(&thread, NULL, thread_func, NULL) != 0)

връщане EXIT_FAILURE;

за (I = 0; I< 20; i++)

if (pthread_join(thread, NULL) != 0)

връщане EXIT_FAILURE;

връщане EXIT_SUCCESS;

Представената програма използва две нишки, които отпечатват съобщения към конзолата, едната отпечатва "a", втората - "b". Изходът на съобщението е смесен в резултат на превключване на изпълнение между нишки или едновременно изпълнение на многопроцесорни системи.

Програмата C създава една нова нишка за отпечатване на "b", а основната нишка отпечатва "a". Основната нишка (след отпечатването на "aaaaa....") изчаква дъщерната нишка да завърши.

Въпроси за сигурност

  1. Какво е паралелна програма?
  2. Каква е разликата между процес и нишка за изпълнение?
  3. Може ли програма да създаде 5 нишки, когато работи на четириядрен процесор?
  4. Какви са характеристиките на паралелните програми със споделена памет?
  5. Какви софтуерни инструменти съществуват за разработване на паралелни програми?
  6. Защо OpenMP стана широко разпространен при създаването на програми за компютри, а не, например, MPI?
програмни изчисленияна компютър трябва да се нарича паралелен. Но това не е единственият въпрос, на който бих искал да получа отговор. Също толкова важно е да разберете защо да преминете от простия, познат, разбираем свят на последователните изчисления към трудния за разбиране свят на паралелните изчисления. Какви са предимствата на паралелните изчисления и какви проблеми очакват програмиста при създаване на програми, ориентирани към паралелни изчисления. За да отговорим на тези въпроси, нека направим кратка екскурзия в историята на развитието на компютрите.

Първите компютри са изградени според принципите, формулирани от Фон Нойман. Те имаха три основни компонента - памет, процесор и определен набор от външни устройства, които осигуряват въвеждане и извеждане на информация.

Паметта е била многостепенна и за първите компютри е съдържала външна памет и вътрешна памет - оперативна и регистрова. Външната памет (на магнитни ленти, перфокарти, дискове) дава възможност за запазване на програми и данни, независимо дали компютърът е включен или не. Вътрешната памет съхранява информация само за продължителността на компютърната сесия. Когато компютърът беше изключен, съдържанието на вътрешната памет изчезна.

За да може една програма да бъде изпълнена на компютър, тя трябва да бъде заредена в RAM. Те се съхраняват там по абсолютно същия начин като данните, обработвани от тази програма. Принципът на програма, съхранявана в паметта, е един от основните принципи на фон ноймановите компютри.

Използвана е регистрационна памет, докато са се извършвали изчисленията. Преди да може да се извърши каквато и да е операция върху данни, данните трябва да бъдат разпределени в регистрите. Този най-бърз тип памет осигурява необходимата скорост при извършване на операции с данни.

Всички операции - операции с данни и операции за контрол на изчислителния процес - бяха извършени от процесора. Компютърният процесор имаше специфичен набор от команди. Този набор беше достатъчно общ, за да изчисли всяка потенциално изчислима функция. От друга страна, този набор гарантира относителната лекота на писане на програми от хора.

Програмите за първите компютри представляват последователност от команди, включени в валидния набор от команди на процесора. Изпълнението на програмата на компютър беше доста просто. Във всеки един момент една програма работеше на компютъра. Процесорът, в съответствие с програмата, последователно изпълнява една инструкция след друга. Всички компютърни ресурси - памет, процесорно време, всички устройства - бяха на пълно разположение на програмата и нищо не можеше да попречи на нейната работа (освен, разбира се, човек). Нямаше и следа от паралелизъм.

Тази идилия не продължи дълго поради неефективното използване на ресурсите на компютрите, които бяха изключително скъпи в онези дни. Тогава компютрите не се изключваха - една програма заместваше друга.

Съвсем скоро, заедно с процесора, който стана известен като централен процесор, компютърът започна да има допълнителни процесори, предимно специализирани процесори за входно-изходни устройства, отговорни за изпълнението на най-бавните команди. Това направи възможно организирането на пакетен режим на изпълнение на програмата, когато няколко програми се изпълняват едновременно на компютъра - една програма може да отпечата резултатите от работата, друга може да бъде изпълнена, трета може да въведе необходимите данни, например от магнитна лента или друг външен носител.

Революционна стъпка е появата през 1964 г. на операционната система IBM - OS 360. Появата на компютъра операционна системастана негов суверенен господар – управител на всички негови ресурси. Сега потребителската програма можеше да се изпълнява само под контрола на операционната система. операционна система позволи да се решат два важни проблема - от една страна, да се осигури необходимото обслужване на всички програми, работещи едновременно на компютъра, от друга страна, ефективно да се използват и разпределят съществуващите ресурси между програмите, изискващи тези ресурси. Появата на операционните системи доведе до прехода от режим на работа с една програма към режим на работа с много програми, когато няколко програми се изпълняват едновременно на един компютър. Мултипрограмираневсе още не е паралелно програмиране, но това е стъпка в посока на паралелно изчисление.

Мултипрограмирането е паралелното изпълнение на няколко програми. Мултипрограмирането ви позволява да намалите общото време за изпълнение.

Паралелното изчисление се отнася до паралелно изпълнение на една и съща програма. Паралелното изчисление ви позволява да намалите времето за изпълнение на една програма.

Имайте предвид, че наличието на няколко процесора на компютър е необходимо условие за мултипрограмиране. Наличието на операционна система, която организира взаимната работа на процесорите, е достатъчно за реализиране на мултипрограмиране. За паралелните изчисления се налага допълнително изискване - това е изискване за самата програма - програмата трябва да позволява възможност за паралелизиране на изчисленията.

Появата на операционната система означава, че компютърът не може да се разглежда само като хардуер (памет, процесори, други устройства). Сега той има два компонента - твърд и мек - хардуерни и софтуерни компоненти, които се допълват взаимно. През половинвековното съществуване на компютрите и двата компонента се развиха бързо.

Оборудването се характеризира с експоненциален растеж, което се отразява в добре известния емпиричен закон на Мур - всички най-важни характеристики нарастват експоненциално - обем на паметта на всички нива, намаляване на времето за достъп до паметта, скорост на процесора. Според закона на Мур (Гордън Мур е един от основателите на Intel), всяка година и половина стойностите на характеристиките се удвояват. Броят на процесорите, включени в компютъра, също нараства. Променен и компютърна архитектура. Тези промени бяха до голяма степен стъпки към паралелизиране на изчисленията. Ето само няколко промени в архитектурата на процесора, пряко свързани с процеса на паралелизиране:

  • Обработка на команди за конвейер. Процесът на изпълнение на поток от команди от процесора вече не се счита за последователно изпълнение на команда след команда. Командният поток беше обработен по конвейер, така че няколко команди бяха подготвени за изпълнение наведнъж. С тръбопроводната обработка команди, които не са свързани помежду си с данни, могат да се изпълняват едновременно, което е истински паралелизъм.
  • "Дълги команди" Архитектурата на някои компютри включва няколко процесора, които позволяват логически и аритметични операции с цели числа, и няколко процесора, които извършват операции с числа с плаваща запетая. Дълга команда ви позволи да посочите в една команда действията, които всеки от съществуващите процесори трябва да извърши. Отново, това направи възможно прилагането на паралелизъм на хардуерно ниво.
  • Векторни и матрични процесори. Наборът от инструкции на такива процесори включва основни операции върху вектори и матрици. С една команда, например, можете да добавите две матрици. Тази команда всъщност прилага паралелно изчисление. Приложенията, при които тези операции са в основата на обработката на данни, са широко разпространени. Хардуерно базираната паралелна обработка на данни може значително да увеличи ефективността на приложенията от този клас.
  • Графични процесори. Друг важен тип приложения, при които се извършва паралелно изпълнение на хардуерно ниво, са приложенията с интензивна графика. Тази обработка се извършва от GPU. Графичното изображение може да се разглежда като колекция от точки. Обработката на изображението често се свежда до извършване на една и съща операция във всички точки. Паралелизирането на данни се прилага лесно в такава ситуация. Следователно графичните процесори отдавна са многоядрени, което позволява паралелна обработка и ефективна обработка на изображения.
  • Суперкомпютри. Суперкомпютрите са компютри с най-високи характеристики на производителност в момента. Те се състоят от стотици хиляди процесори. Ефективното използване на суперкомпютри изисква възможно най-широко паралелизиране на изчисленията.

В научните изследвания и новите технологии винаги има проблеми, които изискват пълната мощност на съществуващите изчислителни системи. Научният потенциал на една страна до голяма степен се определя от наличието на суперкомпютри. Концепцията за суперкомпютър е относителна концепция. Характеристиките на суперкомпютър от преди десет години днес отговарят на характеристиките на обикновен компютър. Днешните суперкомпютри имат изпълнение, измерено в петафлопс (10 15 операции с плаваща запетая в секунда). До 2020 г. се очаква изпълнениесуперкомпютрите ще се увеличат с 1000 пъти и ще се измерват в екзафлопс.

Класификация на компютрите

Светът на компютрите е разнообразен, вариращ от миниатюрни вградени компютри до многотонни суперкомпютри, обитаващи отделни сгради. Те могат да бъдат класифицирани по различни начини. Нека разгледаме една от първите и най-прости класификации - класификацията на Флин, базирана на това как е организирана обработката на данни в компютъра. Според тази класификация всички компютри (изчислителни системи) могат да бъдат разделени на четири класа - компютри със следната архитектура:

  • SISD (Single Instruction stream - Single Data stream) - единичен команден поток - единичен поток от данни. Този клас включва обикновени „серийни“ компютри с архитектура на фон Нойман, когато програмните команди се изпълняват последователно, обработвайки следващия елемент от данни.
  • SIMD (Single Instruction stream - Multiple Data stream) - единичен команден поток - множествен поток от данни. Този тип включва компютри с векторни и матрични процесори.
  • MISD (Multiple Instruction stream - Single Data stream) - множествен команден поток - единичен поток от данни. Този тип включва компютри с конвейерен тип обработка на данни. Мнозина обаче смятат, че такива компютри трябва да бъдат класифицирани като първия тип, а компютрите от клас MISD все още не са създадени.
  • MIMD (Multiple Instruction stream - Multiple Data stream) - множествен команден поток - множествен поток от данни. Класът MIMD е изключително широк и в момента включва много компютри с доста различни архитектури. Следователно се предлагат други класификации за по-точно класифициране на компютрите, включени в класа MIMD.

Няма да разглеждаме подробна класификация на компютрите от клас MIMD. Нека се спрем само на друг начин за разделяне на компютрите на три класа:

  • Многопроцесорните изчислителни системи са компютри с множество процесори, работещи в споделена памет. Този клас включва повечето многоядрени компютри, продавани на пазара днес.
  • Мултикомпютърни изчислителни системи - представляват множество компютри, свързани с високоскоростни комуникационни линии. Всеки компютър има собствена памет и обменя съобщения с други компютри в системата за прехвърляне на данни. Този клас включва клъстери. Клъстерът е изчислителен комплекс, разглеждан като едно цяло, със специален компютър, който играе ролята на сървър. Тъй като компютрите, които образуват клъстер, могат да бъдат обикновени компютри, клъстерите са сравнително евтини. Повечето от топ 500 суперкомпютри са клъстери.
  • Хибридни изчислителни системи – състоят се от множество възли, всеки от които може да бъде мултикомпютър, мултипроцесорен, графичен или векторен процесор. Такива комплекси, като правило, са суперкомпютри.

Концепцията за паралелно изчисление

ОСНОВИ НА ПАРАЛЕЛНОТО ИЗЧИСЛЕНИЕ

Лекция №6


Под паралелни или едновременни изчисленияможете да разберете процеси за решаване на проблеми, при които няколко изчислителни операции могат да се изпълняват едновременно едновременно

Паралелното изчисление формира основата на суперкомпютърните технологии и високопроизводителните изчисления

Паралелна обработка

Ако определено устройство извършва една операция за единица време, тогава то ще извърши хиляда операции в хиляда единици. Ако приемем, че има пет идентични независими устройства, способни да работят едновременно, тогава система от пет устройства може да извърши същите хиляда операции не за хиляда, а за двеста единици време.

По подобен начин система от N устройства ще извърши същата работа за 1000/N единици време. Подобни аналогии могат да се намерят и в живота: ако един войник прекопае градина за 10 часа, то рота от петдесет войници със същите способности, работещи едновременно, ще се справят със същата работа за 12 минути - принципът на паралелизма в действие!

Пионер в паралелната обработка на потоци от данни беше академик А.А. Самарски, който извърши изчисленията, необходими за симулиране на ядрени експлозии в началото на 50-те години. Самарски реши този проблем, като настани няколко десетки млади дами с сумиращи машини на масите. Младите дами прехвърляха данни една на друга просто с думи и записваха необходимите числа на сумиращите машини. Така по-специално е изчислена еволюцията на взривната вълна.

Имаше много работа, младите дами бяха уморени, а Александър Андреевич вървеше между тях и ги насърчаваше. Това, може да се каже, беше първата паралелна система. Въпреки че изчисленията за водородната бомба бяха извършени майсторски, тяхната точност беше много ниска, тъй като имаше малко възли в използваната мрежа и времето за изчисление беше твърде дълго.

Конвейерна обработка

Идеята на тръбопроводната обработка е да се изолират отделни етапи на извършване на обща операция и всеки етап, след като приключи своята работа, ще предаде резултата на следващия, като същевременно получава нова порция входни данни. Получаваме очевидна печалба в скоростта на обработка чрез комбиниране на предварително разпределени операции.

Да приемем, че в една операция има пет микрооперации, всяка от които се извършва за една единица време. Ако има едно неделимо серийно устройство, то ще обработи 100 двойки аргументи в 500 единици. Ако всяка микрооперация е отделена в отделен етап (или иначе наречен етап) на конвейерно устройство, тогава на петата единица време, на различен етап от обработката на такова устройство, първите пет двойки аргументи ще бъдат и целият комплект от сто чифта ще бъде обработен за 5 + 99 = 104 единици време - ускорението в сравнение със серийно устройство е почти пет пъти (според броя на етапите на конвейера).



Модели на паралелни компютри (класификация на Флин)

· „Един поток от команди – един поток от данни“ (SISD – „Единични данни с една инструкция“)

Отнася се за архитектурата на фон Нойман. SISD компютрите са обикновени, „традиционни“ последователни компютри, в които се извършва само една операция върху един елемент от данни (числова или някаква друга стойност) във всеки даден момент. Повечето съвременни персонални компютри попадат в тази категория.

· „Един команден поток – много потоци от данни“ (SIMD – „Единична инструкция – множество данни“)

SIMD (единична инструкция, множество данни)- принцип на компютърните изчисления, който позволява паралелизъм на ниво данни. SIMD компютрите се състоят от един команден процесор (контролен модул), наречен контролер, и няколко модула за обработка на данни, наречени обработващи елементи. Контролният модул приема, анализира и изпълнява команди.

Ако в командата се срещнат данни, контролерът изпраща команда до всички елементи на процесора и тази команда се изпълнява на няколко или всички елементи на процесора. Всеки обработващ елемент има собствена памет за съхранение на данни. Едно от предимствата на тази архитектура е, че в този случай логиката на изчислението се реализира по-ефективно. SIMD процесорите се наричат ​​още векторни процесори.

· „Много командни потоци – един поток от данни“ (MISD – „Множество инструкции – единични данни“)

Компютри от този клас практически няма и е трудно да се даде пример за тяхното успешно внедряване. Един от малкото е систоличен масив от процесори, в който процесорите са разположени във възлите на правилна решетка, чиято роля на ръбове играят междупроцесорните връзки. Всички елементи на процесора се управляват от общ тактов генератор. Във всеки работен цикъл всеки обработващ елемент получава данни от своите съседи, изпълнява една команда и предава резултата на своите съседи.

Извикват се масиви от PE с директни връзки между близки PE систолно. Такива масиви са изключително ефективни, но всеки от тях е фокусиран върху решаването на много тесен клас проблеми. Нека да разгледаме как можете да изградите систоличен масив за решаване на определен проблем. Нека, например, искате да създадете устройство за изчисляване на матрица D=C+AB, Къде

Тук всички матрици са лентови матрици от ред п. Матрица Аима един диагонал над и два диагонала под основния; матрица Б- един диагонал под и два диагонала над основния; матрица Втри диагонала над и под основния. Нека всеки PE може да изпълнява скаларна операция c+abи едновременно предават данни. Следователно всеки PE трябва да има три входа: a, b, cи три изхода: a, b, c. вход ( в) и почивните дни ( навън) данните са свързани с отношения

a out = a in, b out = b in, c out = c in + a in *b in;

Ако по време на операцията някои данни не са получени, тогава ще приемем, че те са определени като нули. Нека освен това приемем, че всички PE са разположени на равнина и всеки от тях е свързан с шест съседни. Ако подредите данните, както е показано на фигурата, веригата ще изчисли матрицата г.

Масивът работи в тактови цикли. По време на всеки тактов цикъл всички данни се преместват към съседни възли в посоките, посочени от стрелките.

Фигурата показва състоянието на систоличния масив в определен момент от времето. В следващия тактов цикъл всички данни ще се преместят в един възел и елементи a11, b11, c11ще завърши в едно PE, разположено в пресечната точка на пунктираните линии. Следователно изразът ще бъде оценен c11+a11b11.В същия часовник, данни а12и b21ще се доближи много до PE, разположено в горната част на систоличния масив.

В следващия тактов цикъл всички данни отново ще преместят един възел по посока на стрелките и ще се появят в горния PE а12и b21и резултата от предишната работа на намиращото се по-долу РЕ, т.е. c11+a11b11. Следователно изразът ще бъде оценен c11+a11b11+a12b21. Това е елемент d11матрици г.

Продължавайки поетапното изследване на процеса, можем да проверим, че при PE изходите, съответстващи на горната граница на систоличния масив, матричните елементи се извеждат периодично след три стъпки г, докато елементи от същия диагонал се появяват на всеки изход. В около 3nцикли, изчислението на цялата матрица ще бъде завършено г. В този случай натоварването на всяка систолна клетка е асимптотично равно 1/3 .

„Много командни потоци – много потоци от данни“ (MIMD – „Множество инструкции – множество данни“)

Тази категория компютърни архитектури е най-богатата ако имайте предвид примери за успешните му реализации. Тя включва симетрични паралелни изчислителни системи, работни станции с множество процесори, клъстери на работни станции и др.

Огромната производителност на паралелните компютри и суперкомпютрите е повече от компенсирана от трудностите при използването им. Да започнем с най-простите неща. Имате програма и достъп до, да речем, компютър с 256 процесора. какво очакваш Да, ясно е: вие съвсем законно очаквате, че програмата ще се изпълни 256 пъти по-бързо, отколкото на един процесор. Но точно това най-вероятно няма да се случи.

Изпращането на вашата добра работа в базата знания е лесно. Използвайте формата по-долу

Студенти, докторанти, млади учени, които използват базата от знания в обучението и работата си, ще ви бъдат много благодарни.

Публикувано на http://www.allbest.ru/

Публикувано на http://www.allbest.ru/

  • Въведение
  • 1. Уместност на темата
  • 2. Увеличаване на броя на ядрата
  • 3. Технология NVIDIA CUDA
  • 4. Разлика между CPU и GPU
  • Заключение
  • Въведение
  • Паралелизиране на изчисленията е разделянето на големи задачи на по-малки, които могат да се изпълняват едновременно. Паралелното изчисление обикновено изисква известни координирани усилия. Паралелното изчисление се предлага в няколко форми (инструкции, битове, данни, нива на задачи). Паралелното изчисление се използва от много години главно във високопроизводителни изчисления. Но наскоро ситуацията се промени. Имаше търсене на такива изчисления поради физически ограничения върху растежа на тактовата честота на процесора. Паралелното изчисление се превърна в доминираща идея в компютърната архитектура. Той прие формата на многоядрени процесори.
  • Използването на паралелни изчислителни системи се определя от стратегическите насоки на развитие в компютърната индустрия. Основното обстоятелство беше не само ограничаването на скоростта на машините, базирани на последователна логика, но и наличието на задачи, за които наличието на компютърна технология все още не е достатъчно. Задачите от тази категория включват моделиране на динамични процеси.
  • Появата на многоядрени процесори бележи скок в развитието на ефективните суперкомпютри, които могат да се похвалят с по-високи съотношения производителност/цена от системите, базирани на суперкомпютри. Използването на многоядрени процесори осигурява гъвкавост, по-специално за различни конфигурации, както и мащабиране на мощността в изчислителните системи - от персонални компютри, сървъри, работни станции и завършвайки с клъстерни системи.
  • 1. Уместност на темата
  • През последните години се появиха голям брой евтини клъстерни паралелни изчислителни системи, които доведоха до бързото развитие на паралелните изчислителни технологии, включително в областта на високопроизводителните изчисления. Повечето големи производители на микропроцесори започнаха да преминават към многоядрени архитектури, което повлия на промяната в ситуацията в областта на паралелните изчислителни технологии. Промяната в хардуерната база води до промяна в конструкцията на паралелните алгоритми. За внедряване в многоядрени изчислителни архитектури са необходими нови паралелни алгоритми, които отчитат новите технологии. Ефективността на използването на изчислителните ресурси ще зависи от качеството на самите паралелни приложения и специализираните библиотеки, насочени към многоядрени архитектури.
  • Използването на високопроизводителна технология при моделиране на реални технически, икономически и други процеси, описани чрез системи от високомерни обикновени диференциални уравнения, е не само оправдано, но и необходимо. Паралелизиране на изчисленията в многопроцесорни и паралелни структури е ефективен начин за подобряване на производителността. Така че използването на паралелни изчислителни системи е доста важна посока в развитието на компютърните технологии.

2. Увеличаване на броя на ядрата

Първият процесор за масово използване беше POWER4 с две PowerPC ядра на един чип. Издаден от IBM през 2001 г.

Производителите на процесори Intel, AMD, IBM, ARM разпознаха увеличаването на броя на ядрата като една от приоритетните области за увеличаване на производителността.

През 2011 г. бяха пуснати 8-ядрени процесори за домашни компютри и 16-ядрени процесори за сървърни системи.

Има разработки на процесори с голям брой ядра (повече от 20), които са намерили приложение в конкретни устройства.

Двуядрените процесори съществуваха по-рано, например IBM PowerPC-970MP (G5H). Но такива процесори се използват в тесен кръг от специализирани задачи.

През април 2005 г. AMD представи 2-ядрения процесор Opteron. AMD64 архитектура. предназначени за сървъри. През май 2005 г. Intel представи процесора Pentium D x86-64. Стана първият 2-ядрен процесор за домашни компютри.

През март 2010 г. AMD представи 12-ядрени серийни сървърни процесори Opteron 6100 (архитектура x86/x86-64).

През август 2011 г. AMD представи 16-ядрените сървърни процесори Opteron 6200, които съдържат два 8-ядрени (4-модулни) чипа в един пакет и са съвместими с платформата AMD Opteron 6100 (Socket G34).

3. Технология NVIDIA CUDA

Голямо количество паралелни изчисления е свързано с 3D игри. Паралелните векторни изчисления на устройства с общо предназначение с многоядрени процесори се използват в 3D графики, като се постига висока пикова производителност. Универсалните процесори не могат да направят това. Максималната скорост се постига само в редица удобни задачи, които имат някои ограничения. Но все пак такива устройства се използват широко в области, където първоначално не са били предназначени. Например процесорът Cell, разработен от алианса Sony-Toshiba-IBM в игровата конзола Sony PlayStation 3, или модерни видеокарти от NVIDIA и AMD.

Преди няколко години започнаха да се появяват неграфични изчислителни технологии с общо предназначение GPGPU за 3D видео ускорители. Съвременните видео чипове имат стотици математически изпълнителни единици, такава мощност може да помогне значително да ускори много изчислително интензивни приложения. Настоящите поколения графични процесори имат гъвкава архитектура, която заедно със софтуерните и хардуерните архитектури и езиците от високо ниво прави възможно да ги направи много по-достъпни.

Появата на сравнително бързи и гъвкави програми за шейдъри заинтересува разработчиците в създаването на GPGPU, които са способни да изпълняват съвременни видео чипове. Разработчиците искаха да използват GPU за изчисляване не само на изображения в игри и 3D приложения, но и да ги използват в други области на паралелни изчисления. За да направим това, използвахме API на OpenGL и Direct3D графични библиотеки. Данните бяха прехвърлени към видеочипа като текстури, а изчислителните програми бяха поставени под формата на шейдъри. Основният недостатък на този метод е значителната сложност на програмирането, ниският обмен на данни между GPU и CPU и някои други ограничения.

Водещите производители на видеочипове NVIDIA и AMD представиха платформи за паралелни изчисления - съответно CUDA и CTM. Видеокартите вече имат хардуерна поддръжка за директен достъп до изчислителните ресурси. CUDA е разширение на езика за програмиране CTM е по-скоро като виртуална машина, която изпълнява само код за асемблиране. И двете платформи премахнаха ограниченията на предишните версии на GPGPU, които използваха традиционния графичен конвейер и, разбира се, Direct3D и Open GL графичните библиотеки.

OpenGL е по-преносим и също така многофункционален поради природата си с отворен код. Но няма да позволи един и същ код да се използва на чипове от различни производители. Такива методи имат много недостатъци, те не са удобни и имат малка гъвкавост. Те също така не ви позволяват да използвате специфичните възможности на някои видеокарти, например бърза споделена памет.

Точно това се случи с NVIDIA, за да пусне платформата CUDA - C-подобен език за програмиране, оборудван със собствен компилатор и също така има библиотеки за GPU изчисления. Писането на добър код за видео чипове не е лесно, но CUDA ви дава повече контрол върху хардуера на видеокартата. CUDA се появи с видеокарти от серия 8, която поддържа изчисления с двойна точност в 32- и 64-битови Windows, Linux, MacOS X.

4. Разлика между CPU и GPU

Увеличаването на тактовата честота приключи поради високата консумация на енергия. Увеличаването на производителността се дължи на увеличаването на броя на ядрата на един чип. В момента за домашни потребители се продават процесори с до осем ядра и брой нишки до 16. В такива процесори всяко ядро ​​работи отделно.

Специални векторни възможности (SSE инструкции) за 4-компонентни (с плаваща запетая с единична точност) и 2-компонентни (с двойна точност) вектори се появиха в процесорите с общо предназначение поради високите изисквания на графичните приложения. Следователно използването на GPU е по-изгодно, защото Те първоначално са предназначени за такива задачи.

В чиповете на NVIDIA основното устройство е мултипроцесор с 8-10 ядра и около сто ALU с няколко хиляди регистъра и голяма споделена памет. Видеокартата има глобална памет, достъпна от всички мултипроцесори, локална памет във всеки мултипроцесор, както и памет за константи.

В GPU ядрата са SIMD (единичен поток от инструкции, множество потокове от данни) ядра. Тези ядра изпълняват едни и същи инструкции по едно и също време. Това е стилът на програмиране на графични алгоритми. Той е специфичен, но ви позволява да увеличите броя на изчислителните единици поради своята простота.

Основните разлики между архитектурите (GPU и CPU): CPU ядрата изпълняват една нишка от последователни инструкции с максимална производителност, GPU изпълнява голям брой паралелни нишки инструкции. Процесорите с общо предназначение са насочени към постигане на висока производителност на една нишка с инструкции, обработвайки числа с и без плаваща запетая. Достъпът до паметта е произволен.

Политиката на разработчиците на CPU е да получават повече инструкции, изпълнявани паралелно, за да увеличат производителността. Следователно, започвайки с процесорите Intel Pentium, се появи суперскаларна технология за изпълнение, която представлява изпълнението на 2 инструкции за тактов цикъл, а процесорът Pentium Pro се отличава с изпълнение на инструкции извън реда.

Видеочиповете имат по-проста работа и са паралелизирани от самото начало. Чипът взема група полигони, всички необходими операции и произвежда пиксели. Полигоните и пикселите се обработват независимо един от друг. Ето защо GPU има толкова голям брой процесори. Също така, съвременните графични процесори са способни да изпълняват повече от една инструкция за тактов цикъл.

Друга разлика между CPU и GPU: принципът на достъп до паметта. В GPU е последователен и предвидим, т.к ако текстурите са преброени, това означава, че след известно време ще дойде ред на съседните текстури. Следователно организацията на паметта на видеокартата и централния процесор е различна. И поради тази причина видеочипът не се нуждае от голяма кеш памет, а за текстури са необходими само около 128-256 kB.

Работата с памет също е различна. Централните процесори имат вградени контролери на паметта, графичните процесори обикновено имат няколко от тях, до осем 64-битови канала. Освен това се използва много бърза памет, следователно честотната лента на паметта е по-висока, което е плюс за паралелни изчисления, работещи с огромни потоци от данни.

В процесора голям брой транзистори се изразходват за командни буфери, предвиждане на хардуерни разклонения и огромни количества кеш памет. Всички тези блокове са необходими за ускоряване на малкото командни потоци. В GPU транзисторите отиват към масиви от изпълнителни единици, малка споделена памет, блокове за контрол на потока и контролери на паметта. Всичко това не ускорява изпълнението на отделни нишки, но ви позволява да обработвате огромен брой от тях едновременно.

Кеширане. Процесорът използва кеша, за да намали забавянето при достъп до паметта, което води до повишена производителност. Графичният процесор използва кеш, за да увеличи пропускателната способност. Процесорът намалява забавянето на достъпа до паметта чрез голям кеш и предсказване на разклоненията на кода. Тези хардуерни части са големи върху чипа, поради което консумират много енергия. Графичните процесори решават проблема със забавянето на достъпа до паметта по друг начин: изпълнявайки хиляди нишки едновременно. Когато една нишка чака данни, друга нишка извършва изчисленията без изчакване или забавяне.

Като цяло можем да направим следния извод: видеочиповете са предназначени за паралелни изчисления с голямо количество данни и голям брой аритметични операции.

5. Първо използване на изчисления на графични ускорители

Историята на използването на чипове за математически изчисления започва много отдавна. Първите опити бяха примитивни и използваха някои функции от Z-буфериране и растеризация. Но с появата на шейдърите започна ускорението. През 2003г SIGGRAPH има нов раздел за изчисления и получи GPGPU.

BrookGPU. Известен компилатор на езика за програмиране Brook. Стриймва се. Той е специално проектиран за GPU изчисления. Разработчиците са използвали API: Direct3D или OpenGL. Това значително ограничи използването на графични процесори, т.к шейдърите и текстурите са били използвани в 3D графики и от специалистите по паралелно програмиране не се изисква да знаят нищо. Те използват текущи нишки и ядра. Брук успя да помогне малко с тази задача. Разширенията на езика C помогнаха да се скрие 3D API от програмистите и предоставиха видеочипа като паралелен копроцесор. Компилаторът компилира кода и го свърза с библиотеката DirectX, OpenGL или x86.

6. Области на приложение на паралелни изчисления на графични ускорители

Ето средните цифри за увеличението на изчислителната производителност, получени от изследователи по целия свят. При преминаване към GPU увеличението на производителността е средно 5-30 пъти, а в някои примери достига до 100 пъти (обикновено това е код, който не е подходящ за изчисления с помощта на SEE.

Ето няколко примера за ускорения:

· Флуоресцентна микроскопия – 12 пъти;

· Молекулярна динамика – 8-16 пъти;

· Електростатика (директно и многостепенно Кулоново сумиране) – 40-120 пъти и 7 пъти.

ядрена процесорна графика

Заключение

В резюме успяхме да разгледаме паралелните изчисления на многоядрени процесори, както и технологиите CUDA и CTM. Беше обсъдена разликата между CPU и GPU, какви бяха трудностите при използването на видеокарти в паралелни изчисления без CUDA технология и бяха разгледани областите на приложение.

Резюмето не разглежда използването на паралелни изчисления в централни процесори с интегрирано видео ядро. Това са AMD A-серия процесори (AMD A10, AMD A8, AMD A6, AMD A4) и Intel i3/i5/i7 серия процесори с вградено HD Graphics видео ядро.

Списък на използваната литература

1. Уебсайт ixbt.com, собственик на Byrds Research and Publishing, Ltd

2. Уебсайт wikipedia.org, собственик Wikimedia Foundation

3. Уебсайт nvidia.ru, собственик на корпорацията NVIDIA

Публикувано на Allbest.ru

...

Подобни документи

    Пакетният метод като основен метод за извършване на комуникационни операции, неговото съдържание и изисквания. Оценка на сложността на операция за пренос на данни между два клъстерни възела. Етапи на развитие на паралелни алгоритми (паралелизиране).

    презентация, добавена на 02/10/2014

    Въведение в историята на развитието на многопроцесорните системи и паралелните изчисления. Персоналните компютри като обикновени еднопроцесорни системи на платформата Intel или AMD, работещи с еднопотребителски операционни системи.

    презентация, добавена на 22.02.2016 г

    Класификация на паралелни изчислителни системи. Основни понятия и компоненти на паралелните компютри, техните компоненти. Характеристики на класификациите на Хендер, Хокни, Флин, Шор. Системи със споделена и локална памет. Методи за разделяне на паметта.

    курсова работа, добавена на 18.07.2012 г

    Математически основи на паралелното изчисление. Свойства на Parallel Computing Toolbox. Разработка на паралелни приложения в Matlab. Примери за програмиране на паралелни задачи. Изчисляване на определен интеграл. Последователно и паралелно умножение.

    курсова работа, добавена на 15.12.2010 г

    Разработване на концепции и възможности на ОС. Паралелни компютърни системи и характеристики на техните ОС. Симетрични и асиметрични мултипроцесорни системи. Видове сървъри в системи клиент-сървър. ОС за облачни изчисления. Клъстерни изчислителни системи.

    лекция, добавена на 24.01.2014 г

    Технология за разработване на паралелни програми за многопроцесорни изчислителни системи със споделена памет. Синтаксис, семантика и структура на OpenMP модела: директиви, процедури и променливи на средата. Паралелизиране на данни и операции, синхронизация.

    презентация, добавена на 02/10/2014

    Паралелни изчислителни системи, тяхната обща характеристика и функционални особености, оценка на възможностите, вътрешна структура и взаимосвързаност на елементите, видове: еднопроцесорни и многопроцесорни. Паралелна форма на алгоритъма, нейното представяне и реализация.

    тест, добавен на 06/02/2014

    Предимства на многопроцесорните системи. Създаване на програма, реализираща работата на многопроцесорна система със споделена памет за обработка на различен брой заявки, както и различен брой процесори. Модели на изчисления на векторни и матрични компютри.

    курсова работа, добавена на 21.06.2013 г

    Абстрактни модели и методи за паралелна обработка на данни, допустима грешка на изчисленията. Концепцията за паралелен процес, техните гранули за синхронизация и паралелизиране, определението на закона на Амдал. Архитектура на многопроцесорни изчислителни системи.

    дипломна работа, добавена на 09.09.2010 г

    Еднопроцесорните изчислителни системи не могат да се справят с решаването на военни приложни проблеми в реално време, следователно, за да се увеличи производителността на военните изчислителни системи, се използват многопроцесорни изчислителни системи (MCS).

Многопроцесорността и многоядреността отдавна са станали обичайни сред потребителите, което не пречи на програмистите да не използват напълно или дори просто неправилно присъщите им възможности. Не обещаваме, че след като прочетете тази статия, ще станете гуру на паралелните изчисления в Win среда, но определено ще разберете някои неща.

Въведение

Краят на ерата на 32-битовите камъни наближаваше и беше очевидно, че е необходимо да се увеличи не само мощността, но и битовият капацитет. Разработчиците на процесори се сблъскаха с редица проблеми при увеличаване на тактовата честота: беше невъзможно да се разсее топлината, генерирана от кристала, беше невъзможно допълнително да се намали размерът на транзисторите, но основният проблем беше, че увеличаването на тактовата честота не доведе до подобрение изпълнението на програмите. Причината за това е паралелната работа на съвременните компютърни системи и един процесор, колкото и мощен да е, може да изпълнява само една задача наведнъж. Например, имам 119 процеса, работещи на моята Windows 7 система към момента на писане на това. Въпреки че не всички са на заден план, не всички се нуждаят от висока мощност. На един камък изпълнението на няколко процеса/нишки може да бъде само едновременно. Тоест работата им се редува: след като дадена нишка е завършила своя отрязък от време, през който е завършила полезния товар, текущото й състояние ще бъде съхранено в паметта и ще бъде разтоварено от процесора и заменено от следващата нишка, поставена на опашка за изпълнение - ще се случи превключване на контекста, за което се губи ценно време. Междувременно се извършва обмен на данни между процесора и RAM поради ограничената честотна лента на системната шина, микропроцесорът нервно пуши бамбук, чакайки данни отстрани. Хардуерните и софтуерните програми (например от операционната система) могат да дойдат на помощ, за да заредят данни в кеша. Кешът обаче е много ограничен по размер, така че това решение не може да служи като панацея. Решението беше паралелна обработка, при която няколко процеса се изпълняват едновременно в реално време. И за да се реализира, беше необходимо да се преработи фундаментално и да се преустрои камъкът - да се комбинират два или повече ефективни кристала в едно тяло.

Планиране

При разработването на паралелна програма етапът на проектиране става дори по-важен, отколкото при разработването на еднонишкови приложения. И тъй като всъщност паралелното програмиране се използва от десетилетия в тесен кръг от проблеми, бяха идентифицирани някои доказани концепции. Най-важното е да гледате на развитието по различен начин, а не последователно, да подчертавате единица работа, която се изпълнява, и да декомпозирате задачата. Има три метода: декомпозиция по задачи, декомпозиция по данни, декомпозиция по информационни потоци. Първият метод на декомпозиция е най-простият: ние просто свързваме отделна функция към конкретна нишка и я стартираме за изпълнение. Паралелната обработка е готова. Възможно е обаче да има проблеми - спор, ако изпълнимият модул използва споделени глобални данни. Но ще говорим за това по-късно. Вторият метод също е доста ясен метод за паралелизиране: например голям масив от данни се обработва от няколко нишки, всяка от които работи върху част, ограничена от определени ограничения. Декомпозицията по информационни потоци се използва за задачи, при които работата на една нишка зависи от резултата от изпълнението на друга. Например, когато четете от файл, нишката, която обработва прочетените данни, не може да започне да работи, докато нишката четец не прочете определено количество данни.

Хардуерни решения


Преди да преминат към многоядрени, разработчиците на процесори откриха, че при изпълнение на една нишка ядрото на процесора не се зарежда напълно (мисля, че не е нужно да сте мечтател за това). И тъй като не всички ресурси на микропроцесора се използват за изпълнение на втората програмна нишка (тъй като състоянието на хардуера - изпълнителни единици, кеш - могат да се съхраняват в едно копие), само областта на състоянието на софтуерната архитектура (логика на прекъсване) се нуждае от дублиране. Тази технология се нарича хипер-нишка. Hyperthreading е хардуерен механизъм, при който множество независими хардуерни нишки се изпълняват в един тактов цикъл на едно суперскаларно процесорно ядро. С негова помощ един физически процесор се представя като два логически, тоест така го вижда операционната система, тъй като планирането и изпълнението всъщност се извършват с две ядра. Това се случва чрез непрекъснат поток от команди, изпълнявани на споделен хардуер. Тази технология беше добавена към архитектурата NetBurst, внедрена в процесорите Pentium 4. Следователно, хипернишковостта беше внедрена в най-новите версии на Pentium 4, но някак си не успях да я хвана по това време. Но сега го виждам в процесора Atom, инсталиран в нетбука. В този камък, в допълнение към хипернишката, са внедрени многоядрени (две части), така че виждам четири камъка в операционната система. Но например в Core 2 Duo, както и в Core i5, няма хипернишковост. С помощта на хипернишковостта скоростта на изпълнение на програмите, оптимизирани за многопоточност, беше увеличена с 30%. Бих искал да подчертая, че увеличаването на производителността ще се случи само в специално подготвени приложения.

Едновременно с хипернишковостта, в допълнение към суперскаларната архитектура, беше създадена нова EPIC архитектура, внедрена в процесорите Itanium, но тази тема вече няма да се вписва в днешната статия.

Тогава бяха изобретени многоядрени процесори, които сега се използват навсякъде. Многоядрените процесори поддържат вградена многопроцесорна обработка. В тази архитектура две или повече ядра са внедрени в един процесор, инсталиран в един сокет. В зависимост от дизайна, тези ядра могат да споделят голям кеш на една и съща матрица. Многоядрените процесори също изискват съвместим чипсет. Тъй като всяко ядро ​​е независим изпълнителен модул, многоядрените процесори осигуряват истински паралелизъм - изпълнението на всяка нишка в отделна среда. В случай на наличие на няколко изпълнителни ядра трябва да има начин за обмен на информация между тях, без който просто е невъзможно да се създаде паралелна система и е необходим специален ресурс. За да се постигне това, е изобретен Advanced Programmable Interrupt Controller (APIC). Той обменя информация между процесори/ядра, използвайки механизма за прекъсване на междупроцесора. Последният от своя страна се използва от операционната система за планиране/изпълнение на нишки.

Консумацията на енергия също излиза на преден план. И това се отнася не само за различни мобилни платформи, захранвани от батерии, но и за сървърни системи и настолни компютри. Първите x86 процесори консумират части от вата, докато днешните модели от висок клас могат да консумират 130 вата или повече. Междувременно многоядрените процесори пестят енергия, тъй като подобренията в производителността идват от паралелизъм, а не от увеличаване на тактовите честоти.

Софтуерни решения

Софтуерните решения играят огромна роля в паралелното изпълнение на код. На сцената навлизат както системни софтуерни продукти (операционни системи, компилатори), така и приложения на потребителско ниво. От гледна точка на приложен програмист можем да използваме само второто подмножество. Всъщност това е напълно достатъчно, ако операционната система е надеждна. Повечето от това, което следва, се отнася за Windows NT 6.1, освен ако не е отбелязано друго. Както знаете, Windows NT използва превантивен многонишков модел. Когато дадено приложение стартира, започва процес, в който една или повече нишки могат да изпълняват своята работа, всички от които споделят обща памет и общо адресно пространство. Нишката от своя страна е отделна последователност от команди, която се изпълнява независимо. Има три вида потоци:

  • потребителско ниво - създава се в потребителската програма (на потребителско ниво). Тези нишки в Windows NT са нанесени на нишки на ниво ядро, което е начинът, по който процесорът ги вижда;
  • kernel thread - управлява се от ядрото на операционната система;
  • хардуерна нишка - единица, изпълнявана на процесора.

Създаването на поток става на три етапа. Първо се описва с помощта на API за нишки, след това на етапа на изпълнение това извикване се обработва като извикване на ядрото, в резултат на което се създава нишка, след което се изпълнява в рамките на собствен процес. Но поради факта, че няколко действия се извършват едновременно в програмата, могат да възникнат много проблеми. Те могат удобно да бъдат класифицирани в четири типа. Проблем със синхронизирането възниква, когато една нишка чака изпълнението на друга, която по някаква причина не може да завърши изпълнението. Когато има проблем с комуникацията, една нишка не може да предаде информация на друга навреме, например поради закъснения. Когато единият поток е напрегнат, а другият е хладен, възниква проблем с балансирането. Ако, когато една програма се прехвърли на по-мощен компютър, нейната производителност не се увеличи, тогава те говорят за проблем с мащабируемостта. За да решат всички тези проблеми, примитивите са проектирани да работят в многонишкова среда. Нека да ги разгледаме набързо.

Примитиви за паралелно кодиране

Секции от код, които могат да се използват едновременно от множество нишки и съдържат споделени променливи, се наричат ​​критични секции. В тях четенето и записването на стойности под действието на две или повече нишки може да се случи асинхронно. Това състояние се нарича състезателно състояние. Следователно само една нишка трябва да се изпълнява в критичната секция на всеки интервал от време. За да се гарантира това, се използват примитиви за синхронизация - заключване. Semaphore е исторически първият механизъм за синхронизация, разработен от Dijkstra през 1968 г. Позволява на определен брой нишки да влязат в критичната секция, когато дадена нишка влезе в нея, намалява нейната стойност и я увеличава в момента, в който излезе. Предпоставка е атомарното изпълнение на операциите за проверка на стойността на семафора + увеличаване на стойността, както и проверка на стойността + намаляване на стойността. Разширение на семафора е мютекс, който е просто двоичен семафор и следователно позволява само една нишка да се изпълни в критичната секция. Блокировките за четене и запис позволяват на множество нишки да четат стойността на споделена променлива, разположена в критичната секция, но да пишат само в една. Докато чака, spinlock не блокира, а продължава активно да анкетира заключения ресурс. Spinlocking е лошо решение на проблема със синхронизацията на едноядрен процесор, защото заема всички изчислителни ресурси.

Механизмът на условните променливи е подобен на семафорите, но за разлика от семафорите (и мутексите), те не съдържат реални стойности. Следят за изпълнението на външни условия.

Съвременните езици за програмиране съдържат механизми на високо ниво за опростяване на използването на ключалки и условни променливи („монитори“). Вместо изрично да пише операции за заключване и отключване на част от кода, разработчикът трябва само да декларира критичната секция като синхронизирана.

За обмен на информация между процеси/нишки се използват съобщения, разделени на три групи: вътрешнопроцесни (за пренос на информация между нишки на един процес), междупроцесни (за пренос на информация между процеси – в зависимост от нишки) и процесни – процес (независимо от нишка прехвърляне на информация между процеси).
В същото време, когато използвате ключалки за избягване на състезания, могат да възникнат мъртви ключалки и активни ключалки. Застой възниква, когато една нишка е блокирана в очакване на определен ресурс от друга нишка, но тази нишка не може да го даде (например чака резултат от първата). Застой може да възникне, когато са изпълнени четири добре дефинирани условия (няма да разглеждаме тези условия в тази статия). Следователно, когато пише многонишков код, програмистът има възможност да избегне didlock, но на практика изглежда много по-трудно. Заключването на живо е по-лошо от мъртвото заключване, тъй като в първия случай нишките са блокирани, а във втория са постоянно в конфликт.

Има толкова много несъвместими интерфейси за програмиране на поток от приложения. Всички те основно използват едни и същи примитиви, като единствените разлики са в зависимост от операционната система. В следващите раздели ще разгледаме начини за работа в многонишкова среда и решаване на проблеми с паралелността с помощта на тези интерфейси.


Win32 нишки

От първата версия на Windows NT, многопоточното програмиране се подобрява от версия на версия, докато API за нишки също е подобрен. Така че, когато процес се стартира с помощта на функцията CreateProcess, той има една нишка за изпълнение на команди. Нишката се състои от два обекта: обект на ядрото (чрез който системата управлява нишката) и стек, който съхранява параметрите, функциите и променливите на нишката. За да създадете допълнителна нишка, трябва да извикате функцията CreateThread. Това създава обект на ядрото, компактна структура от данни, използвана от системата за контрол на потока. Този обект всъщност не е нишка. Паметта също се разпределя от адресното пространство на родителския процес за нишката. И тъй като всички нишки на един процес ще се изпълняват в неговото адресно пространство, те ще споделят неговите глобални данни. Нека се върнем към функцията CreateThread и да разгледаме нейните параметри. Първият параметър е указател към структурата PSECURITY ATTRIBUTES, които дефинират атрибути за сигурност и свойства на наследяване, могат да бъдат зададени на стойности по подразбиране чрез предаване на NULL. Вторият параметър от тип DW0RD определя коя част от адресното пространство нишката може да използва за своя стек. Трети параметър PTHREAD START_ROUTIME pfnStartAddr е указател към функцията, която трябва да бъде обвързана с нишката и която тя ще изпълни. Тази функция трябва да бъде във формата DWORD WINAPI ThreadFunc(PVOID pvParam), тя може да изпълнява всякакви операции; когато завърши, той ще върне управлението и потребителският брояч на обекта на ядрото на нишката ще бъде намален с 1; ако този брояч е равен на 0, този обект ще бъде унищожен. Четвъртият параметър на функцията CreateThread е указател към PVOID структура, съдържаща параметър за инициализиране на функцията, изпълнявана в нишката (вижте описанието на третия параметър). Петият параметър (DWORD) определя флаг, показващ дали нишката е активна, след като е създадена. Последният, шести параметър (PDWORD) е адресът на променливата, където ще бъде поставен идентификаторът на нишката; ако подадем NULL, по този начин ще посочим, че не ни е необходим. Ако е успешна, функцията връща манипулатор на поток, който може да се използва за манипулиране на потока; ако не успее, функцията връща 0.


Има четири начина за прекратяване на нишка, три от които са нежелателни: прекратяване на нишката чрез извикване на функцията ExitThread, чрез извикване на TerminateThread или чрез прекратяване на родителския процес, без първо да прекрати нишката. Само 1 начин - самопрекратяването на потока, което се случва при изпълнение на възложените му действия, е благоприятно. Защото само в този случай е гарантирано, че всички ресурси на операционната система ще бъдат освободени и всички C/C++ обекти ще бъдат унищожени с помощта на техните деструктори.

Още няколко думи за създаването на нишка. Функцията CreateThread се намира в API на Win32, а библиотеката на Visual C++ има еквивалент, _beginthreadex, който има почти същия списък от параметри. Препоръчително е да създавате нишки с него, тъй като той не само използва CreateThread, но и извършва допълнителни операции. В допълнение, ако нишката е създадена с помощта на последната, тогава, когато се унищожи, се извиква _endthreadex, който изчиства блока с данни, зает от структурата, описваща нишката.

Нишките са планирани да се изпълняват въз основа на приоритет. Ако всички нишки имат еднакъв приоритет, тогава 20 ms ще бъдат разпределени за всяка нишка (в WinNT). Но това не е вярно. WinNT има 31 (от нула) приоритети на нишки. В същото време 31 е най-високият, само най-критичните приложения могат да работят на него - драйвери на устройства; 0, най-ниският, е запазен за изпълнение на нишката за нулиране на страници. Разработчикът обаче не може изрично да посочи номер на приоритет за изпълнението на неговата нишка. Но в Windows има таблица с приоритети, където са посочени символните обозначения на групираните приоритетни номера. В този случай окончателното число се формира не само въз основа на тази таблица, но и на стойностите на приоритета на родителския процес. Стойностите са скрити зад символни константи поради причината, че Microsoft си запазва правото да ги променя и го използва от версия на версия на своята операционна система. Когато се създава, нишката получава нормално ниво на приоритет. Може да се промени чрез функцията SetThreadPriority, която приема два параметъра: HANDLE hThread - дескриптор на нишката, която се променя, int nPriority - ниво на приоритет (от таблицата). С помощта на функцията GetThreadPriority можете да получите текущия приоритет, като му предадете дескриптора на желаната нишка. Преди да промените приоритета на дадена нишка, тя трябва да бъде спряна; това се прави от функцията SuspendThread. След промяна на приоритета нишката трябва да бъде върната на планировчика, за да планира изпълнението с помощта на функцията ResumeThread. И двете функции получават манипулатор на нишката, върху която работят. Всички описани операции с изключение на спиране и възобновяване се отнасят за процеси. Те не могат да бъдат поставени на пауза/възобновени, защото не консумират процесорно време, така че не са планирани.

Избягване на състезания в Win32

В многонишковите приложения, когато е възможно, е необходимо да се използват атомарни - неделими операции, чието изпълнение не може да бъде намесено от друга нишка. Такива функции в Win32 API имат префикс Interlocked, например, за да увеличите променлива, използвайте InterlockedExchangeAdd(&i, 1) вместо i++. В допълнение към операциите за увеличаване/намаляване, има и операции за атомно сравнение, но ще ги оставим като домашна работа.

Атомните функции обаче ви позволяват да решавате много тесен кръг от проблеми. На помощ идват критичните участъци. Win32 има функции за изрично маркиране на част от кода, който ще бъде изпълнен атомарно. Първо, трябва да създадете екземпляр на структурата на критичната секция, след което във функцията, изпълнявана в нишката, да напишете оператори за влизане и излизане от критичната секция:

CRITICAL_SECTION g_cs; DWORD WINAPI ThreadRun(PVOID pvParam) ( EnterCriticalSection(&g_cs); // Изчисляване на нещо LeaveCriticalSection(&g_cs); return 0; )

Критичните секции в Win32 не са просто код, който може да се изпълнява от множество нишки, те са цял механизъм за синхронизиране на данни. Критичните секции трябва да бъдат възможно най-малки, тоест да включват възможно най-малко изчисления.
За да позволите на множество нишки да четат стойността на дадена променлива и само една да я променя, можете да използвате структурата за „тънко заключване“ на SRWLock. Първата стъпка е да инициализирате структурата чрез извикване на InitializeSRWLock и подаване на указател към нея. След това, по време на запис, ние ограничаваме ресурса до изключителен достъп:

AcquireSRWLockExclusive(PSRWLOCK SRWLock); // Запишете стойността ReleaseSRWLockExclusive(PSRWLOCK SRWLock);

От друга страна, докато четем, извършваме споделен достъп:

AcquireSRWLockShared(PSRWLOCK SRWLock); // Прочетете стойността ReleaseSRWLockShared(PSRWLOCK SRWLock);

Моля, обърнете внимание: всички функции приемат инициализирана SRWLock структура като параметър.
С помощта на условни променливи е удобно да се организира връзката „доставчик-потребител“ (вижте разлагането по информационни потоци), т.е. следващото събитие трябва да се случи в зависимост от предишното. Този механизъм използва функциите SleepConditionVariableCS и SleepConditionVariableSRW за заключване на критичната секция или тънката заключваща структура. Те приемат съответно три и четири параметъра: указател към променлива на условие, очаквана от нишката, указател към критичната секция или SRWLock, използван за синхронизация на достъпа. Следващият параметър е времето (в милисекунди), за което нишката трябва да изчака условието да бъде изпълнено, ако условието не е изпълнено, функцията ще върне False; Последният параметър на втората функция е типът на заключване. За да събудите блокираните нишки, трябва да извикате функцията WakeConditionVariable или WakeAllConditionVariable от друга нишка. Ако тестът, извършен в резултат на извикването на тези функции, потвърди изпълнението на условието, предадено като параметър на тези функции, нишката ще бъде събудена.

В горното описание се запознахме с общите дефиниции на механизмите на семафор и мютекс. Сега нека да видим как се изпълняват в Win32. Можете да създадете семафор с помощта на функцията CreateSemaphore. Към него се предават следните параметри: указател към структурата PSECURITY_ATTRIBUTES, съдържаща параметри за сигурност; максималния брой ресурси, обработвани от приложението; количеството на тези ресурси, налични първоначално; Указател към низ, определящ името на семафора. Когато нишка, чакаща на семафор, иска достъп до ресурс, защитен от семафора, функцията за изчакване на нишката проверява състоянието на семафора. Ако стойността му е по-голяма от 0, тогава семафорът е свободен и стойността му се намалява с 1, а нишката е планирана за изпълнение. Ако семафорът е зает при запитване, стойността му е 0, тогава извикващата нишка преминава в състояние на изчакване. В момента, в който нишката напусне семафора, се извиква функцията ReleaseSemaphore, при която стойността на семафора се увеличава с 1. Мутексите, както и семафорите, са обекти на ядрото. Функционирането на мютексите е подобно на критичните секции на Win32, с разликата, че последните се изпълняват в потребителски режим. Mutex позволява само една нишка да се изпълнява в даден момент и осигурява достъп само до един ресурс. В същото време ви позволява да синхронизирате множество нишки, като съхранявате ID на нишката, която е уловила ресурса, и брояч за броя на улавянията. За да създадете mutex, можете да използвате функцията CreateMutex; нейните параметри са подобни на тези, обсъдени по-горе. Когато изчакването на дадена нишка за mutex завърши успешно, тя получава изключителен достъп до защитения ресурс. Всички други нишки, които се опитват да получат достъп до този ресурс, влизат в състояние на изчакване. Когато нишката, заемаща ресурс, приключи с използването му, тя трябва да освободи мютекса чрез извикване на функцията ReleaseMutex. Тази функция намалява брояча на рекурсия в мютекса с 1. Изборът на механизъм за синхронизация, който да се използва, зависи до голяма степен от времето на неговото изпълнение и кода, в който се използва.

Освен всичко друго, в Windows NT, започвайки от четвъртата версия, има друго ниво на детайлност на нишката - влакна (или нишки). На потребителско ниво нишката на обект на ядрото може да бъде разделена на множество нишки. И в този случай операционната система не знае нищо за тях; цялата работа по планирането и управлението на нишките пада върху плещите на разработчика на приложението.

Заключение

Създаването на модерен софтуер изисква използването на паралелизъм и в бъдеще производителите на процесори заплашват само да увеличат броя на ядрата на един процесор. Многонишковото програмиране обаче има редица трудни аспекти: организиране на синхронно изпълнение на команди, избягване на състезания и в същото време оптимално зареждане на хардуера, за да се постигне повишена производителност поради паралелизъм.

В тази статия първо се занимавахме с примитиви за паралелно кодиране - общи понятия, след което разбрахме как се имплементират в конкретен API - нишки на Win 32. Обхватът на статията не ни позволи да разгледаме други API за многопоточно кодиране. Да се ​​надяваме, че някой ден ще имаме възможност да продължим да обсъждаме тази необходима тема.

Успех ти пожелавам, до скоро!

Операция