Page 81 - 4868
P. 81
79 Ошибка! Стиль не определен.
код рішення задачі i;
oc
}
На жаль, даний підхід досить неефективний, оскільки оператор co
породжує n процесів на кожній ітерації. Створити і знищити процеси
набагато дорожче, ніж реалізувати їх синхронізацію. Тому альтернативна
структура алгоритму робить його набагато ефективнішим – процеси
створюються один раз на початку обчислень, а потім синхронізуються в кінці
кожної ітерації.
process Worker[i = 1 to n] {
while (true) {
код рішення задачі i;
очікування завершення всіх n задач;
}
}
Точка затримки в кінці кожної ітерації представляє собою бар’єр, якого
повинні досягти всі процеси для продовження своєї роботи, тому цей
механізм називається бар’єрною синхронізацією. Бар’єри можуть бути
необхідними в кінці циклів, як в даному прикладі, або на проміжних етапах
обчислень, як це буде продемонстровано нижче.
Найпростіший спосіб описати вимоги до бар’єра полягає у використанні
спільного цілочисельного лічильника, наприклад з назвою count для якого
встановлене нульове початкове значення. Припустимо, що існуєn робочих
процесів, які повинні «зібратися» біля бар’єру. Коли процес підходить до
бар’єру, він збільшує значення змінної count. Коли значення лічильника
count стане рівним n, всі процеси зможуть продовжити свою роботу.
int count = 0;
process Worker[i = 1 to n] {
while (true) {
код реалізації задачі i;
<count = count+1;>
< await(count == n);>
}
}
Оператор await можна реалізувати за допомогою циклу з активним
очікуванням. При наявності неподільної інструкції типу FA, даний бар’єр
можна реалізувати наступним чином:
FA(count, 1);
while (count != n) skip;
Однак даний код не цілком відповідає поставленій задачі. Складність
полягає в тому, що значенням змінної count повинен бути 0 на початку
кожної ітерації, тобто count потрібно обнуляти кожен раз, коли всі процеси
пройдуть бар’єр. Більше того, вона повинна мати значення 0 перед тим, як