Код: Выделить всё
std::vector data;
do { // May run 100 times or more
prepare();
remaining = compute1(my_data);
remaining -= compute2(my_data);
cleanup(my_data);
} while (remaining > 0);
Some benchmarking showed significant time spent synchronizing Потоки, поэтому я подумал о переходе на один параллельный раздел и распределение по данным между потоками. Код будет выглядеть как: < /p>
Код: Выделить всё
std::vector data;
std::atomic remaining;
#pragma omp parallel
{
std::vector my_data;
#pragma for schedule(static)
for (int i = 0; i < data.size(); i++) {
my_data.push_back(data[i]);
}
do { // May run 100 times or more
prepare();
remaining = 0;
remaining += compute1(my_data);
remaining -= compute2(my_data);
cleanup(my_data);
} while (remaining > 0);
}
- Ни один поток не должен выполнять оставшиеся += compute1 () , прежде чем все потоки будут выполнять оставшиеся = 0 В потоках запускаются оставшиеся -= compute2 () инструкция.
- Ни один поток не должен запустить оставшиеся = 0 Инструкция, прежде чем все потоки протестировали предыдущий оставшиеся> 0 Условие. Compute2 () инструкция.
- Ни один поток не должен запустить оставшуюся инструкцию += compute1 () Перед тем, как все потоки запускают инструкцию Prepare () .
- Ни один поток не должен запустить оставшуюся часть -= Compute2 () Перед тем, как все потоки. Вычислить функции).
ограничение № 1 также легко удовлетворить: оставшееся = 0 Инструкция должна быть выполнена с #prongma omp opm . Использование барьеров: < /p>
Код: Выделить всё
std::vector data;
std::atomic remaining;
#pragma omp parallel
{
std::vector my_data;
#pragma for schedule(static)
for (int i = 0; i < data.size(); i++) {
my_data.push_back(data[i]);
}
do { // May run 100 times or more
prepare();
#pragma omp barrier
#pragma omp single
remaining = 0;
remaining += compute1(my_data);
#pragma omp barrier
remaining -= compute2(my_data);
cleanup(my_data);
#pragma omp barrier
} while (remaining > 0);
}
< /code>
Когда я сравниваю это, это показывает значительное улучшение по сравнению с предыдущей версией, где каждая функция была независимо параллелизирована. Моя интуиция заключается в том, что каждый поток, имеющий свои собственные данные, улучшает местонахождение данных и скорость попадания локального CPU/Core Cache.
Но я думаю, что есть многие ненужные ограничения. Если бы у меня был способ иметь какой -то «барьерный раздел», который ни один поток не может оставить до того, как все потоки введут его, я мог бы сделать что -то гораздо менее ограниченное. Я мог бы реализовать это с чем-то вроде: < /p>
std::vector data;
std::atomic remaining;
#pragma omp parallel
{
std::vector my_data;
#pragma for schedule(static)
for (int i = 0; i < data.size(); i++) {
my_data.push_back(data[i]);
}
do { // May run 100 times or more
#pragma omp barriered section
{
prepare();
}
#pragma omp single
remaining = 0;
remaining += compute1(my_data);
#pragma omp barrier
remaining -= compute2(my_data);
#pragma omp barriered section
{
cleanup(my_data);
}
} while (remaining > 0);
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... on-barrier
Мобильная версия