Применение барьеров наиболее легко проиллюстрировать на примере работы с API CUDA. При этом зачастую применяется параллелизм на уровне данных:
1) Например есть большой массив, обработку которого мы хотим распараллелить. Этого можно достичь путем передачи каждому потоку видеокарты - обработку небольшой части этого массива. Тогда все потоки обработают весь исходный массив целиком.
2) Перед тем как обрабатывать, данные сначала нужно "подробить" на "порции" для каждого потока.
3) Загрузить каждую такую "порцию" в память видеокарты.
4) Перед обработкой каждого кусочка исходного массива - зачастую нужно убедиться, что он уже целиком загружен в память видеокарты. - Например есть такие вычисления, при которых нужно учесть "соседние" данные. Как же убедиться, что "соседние" потоки - тоже получили свои данные? - Обобщая на всю задачу - как убедиться, что ВЕСЬ исходный массив, пусть и дробленный на "кусочки" - но загружен в память видеокарты?
5) Для решения п.4 - мы просто указываем в коде потока - вызов барьера. - Пока все потоки не "подойдут" к этому месту кода (началу вычислений, которые следует после загрузки своей порции данных) - потоки будут блокироваться у барьера. Как только все потоки подойдут к барьеру - только тогда барьер позволит им всем "двигаться дальше".
Примерная логика работы потока:
1) Инициализация каких-то первоначальных переменных данного потока. Здесь же поток получает информацию о своем номере, а по своему номеру - он уже может однозначно указать какая именно часть исходных данные ему нужна из массива исходных значений.
2) Команда на загрузку своей порции данных.
3) Вызов функции барьера.
4) Начало обработки своей порции данных.
1) Например есть большой массив, обработку которого мы хотим распараллелить. Этого можно достичь путем передачи каждому потоку видеокарты - обработку небольшой части этого массива. Тогда все потоки обработают весь исходный массив целиком.
2) Перед тем как обрабатывать, данные сначала нужно "подробить" на "порции" для каждого потока.
3) Загрузить каждую такую "порцию" в память видеокарты.
4) Перед обработкой каждого кусочка исходного массива - зачастую нужно убедиться, что он уже целиком загружен в память видеокарты. - Например есть такие вычисления, при которых нужно учесть "соседние" данные. Как же убедиться, что "соседние" потоки - тоже получили свои данные? - Обобщая на всю задачу - как убедиться, что ВЕСЬ исходный массив, пусть и дробленный на "кусочки" - но загружен в память видеокарты?
5) Для решения п.4 - мы просто указываем в коде потока - вызов барьера. - Пока все потоки не "подойдут" к этому месту кода (началу вычислений, которые следует после загрузки своей порции данных) - потоки будут блокироваться у барьера. Как только все потоки подойдут к барьеру - только тогда барьер позволит им всем "двигаться дальше".
Примерная логика работы потока:
1) Инициализация каких-то первоначальных переменных данного потока. Здесь же поток получает информацию о своем номере, а по своему номеру - он уже может однозначно указать какая именно часть исходных данные ему нужна из массива исходных значений.
2) Команда на загрузку своей порции данных.
3) Вызов функции барьера.
4) Начало обработки своей порции данных.
Комментариев нет:
Отправить комментарий