SlideShare una empresa de Scribd logo
1 de 35
Descargar para leer sin conexión
C++17: параллельная версия стандартных
алгоритмов
Евгений Крутько
e.s.krutko@gmail.com
Национальный исследовательский центр "Курчатовский институт"
25.02.2017
Эволюция многопоточной работы в C++
Нам нужно выполнить работу асинхронно
1 int main(){
2 //Here we should use some features to call doWork in parallel
3 doWork(int a);
4 doSomeOtherWork(double t);
5 //Ensure doWork completed
6 return 0;
7 }
Давным-давно...
... у нас не было даже стандарта C++11.
1 //Using POSIX API
2 void* makeDoWork(void *arg) {
3 int *a=reinterpret_cast<int*>(arg);
4 doWork(*a);
5 }
6 int main(){
7 pthread_t thread;
8 int value = 42;
9 pthread_create(
10 &thread,
11 nullptr,
12 makeDoWork,
13 &value);
14 doSomeOtherWork(double t);
15 pthread_join(thread, nullptr);
16 return 0;
17 }
Давным-давно...
... у нас не было даже стандарта C++11.
1 //Using Win API
2 DWORD WINAPI makeDoWork(void *arg) {
3 int *a=reinterpret_cast<int*>(arg);
4 doWork(*a);
5 }
6 int main(){
7 HANDLE thread;
8 int value = 42;
9 thread = CreateThread(
10 NULL,
11 0,
12 makeDoWork,
13 &value,
14 0,
15 NULL
16 );
17 doSomeOtherWork(double t);
18 WaitForSingleObject(thread, INFINITE);
19 return 0;
20 }
Кросс-платформенный подход
И другие
Начиная со стандарта C++11
std::thread
std::async / std::future
1 int main(int argc, char**argv) {
2 std::thread thread;
3 int value;
4 //Do doWork() in new thread
5 thread = std::thread(
6 doWork,
7 std::ref(value));
8 //Do someything else in this thread
9 doSomeOtherWork();
10 //Whait for doWork() finishes
11 thread.join();
12 return 0;
13 }
Начиная со стандарта C++11
std::thread
std::async / std::future
1 int main(int argc, char**argv) {
2 int value;
3 //Do doWork() in new thread
4 auto future = std::async(
5 std::launch::async;
6 doWork,
7 std::ref(value));
8 //Do someything else in this thread
9 doSomeOtherWork();
10 //Whait for doWork() finishes
11 future.get();
12 return 0;
13 }
Нам и этого мало, хочется еще проще
Возможно когда-нибудь :)
1 auto auto(auto auto) { auto; }
Нам и этого мало, хочется еще проще
Возможно когда-нибудь :)
1 auto auto(auto auto) { auto; }
Уже /почти/ в стандарте
1 //Something from <algorythm>
2 std::some_standard_algorythm_with_stl_containers(
3 std::begin(container),
4 std::end(container)
5 );
6 //The same but with specification of execution policy
7 std::some_standard_algorythm_with_stl_containers(
8 ExecutionPolicy policy,
9 std::begin(container),
10 std::end(container)
11 );
Алгоритмы стандартной библиотеки, доступные в
параллельном режиме
Объявлены в заголовочном файле <algorithm>
Пока в стадии TS в заголовочном файле
<experimental/algorithm>
adjacent_difference adjacent_find all_of any_of
copy copy_if copy_n count
count_if equal exclusive_scan fill
fill_n find find_end find_first_of
find_if find_if_not for_each for_each_n
generate generate_n includes inclusive_scan
inner_product inplace_merge is_heap is_heap_until
is_partitioned is_sorted is_sorted_until lexicographical_compare
max_element merge min_element minmax_element
mismatch move none_of nth_element
partial_sort partial_sort_copy partition partition_copy
reduce remove remove_copy remove_copy_if
remove_if replace replace_copy replace_copy_if
replace_if reverse reverse_copy rotate
rotate_copy search search_n set_difference
set_intersection set_symmetric_difference set_union sort
stable_partition stable_sort swap_ranges transform
transform_exclusive_scan transform_inclusive_scan transform_reduce uninitialized_copy
uninitialized_copy_n uninitialized_fill uninitialized_fill_n unique
unique_copy
Политики выполнения
1 //Available from <execution_policy>
2 //While in TS stage from <experimental/execution_policy>
3
4 //Plain old sequenced execution
5 constexpr sequential_execution_policy seq{ };
6 //Parallel execution
7 constexpr parallel_execution_policy par{ };
8 //Parallel with SIMD instructions
9 constexpr parallel_vector_execution_policy par_vec{ };
Политики выполнения
1 //Available from <execution_policy>
2 //While in TS stage from <experimental/execution_policy>
3
4 //Plain old sequenced execution
5 constexpr sequential_execution_policy seq{ };
6 //Parallel execution
7 constexpr parallel_execution_policy par{ };
8 //Parallel with SIMD instructions
9 constexpr parallel_vector_execution_policy par_vec{ };
Стрелять себе по ногам теперь можно еще одним изящным
способом
1 int a[] = {0,1};
2 std::vector<int> v;
3 std::for_each(std::par,
4 std::begin(a),
5 std::end(a),
6 [&](int i) {
7 v.push_back(i*2+1); // Error: data race
8 });
Дайте две!
Как же попробовать? Из документа
https://isocpp.org/files/papers/P0024R2.html
Microsoft MS ParallelSTL page
HPX HPX github
Codeplay Sycl github
HSA HSA for math science page
Thibaut Lutz github
NVIDIA github
http://github.com/eskrut/ParallelSTL.git
Тестовая задача #1
Обычная реализация
1 auto vec = makeShuffledVector();
2 double baseDuration = 0;
3
4 auto vecToSort = vec;
5 {
6 Stopwatch sw("plain sort");
7 std::sort(std::begin(vecToSort), std::end(vecToSort));
8 baseDuration = sw.duration();
9 }
10 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort)))
11 throw std::runtime_error("Failed with plain sort");
Тестовая задача #1
С последовательной политикой
1 //This includes should be from ${T_LUTZ_ROOT}/include
2 #include <numeric>
3 #include <experimental/algorithm>
4
5 /* --- */
6
7 vecToSort = vec;
8 {
9 Stopwatch sw("seq sort", baseDuration);
10 sort(std::experimental::parallel::seq,
11 std::begin(vecToSort), std::end(vecToSort));
12 }
13 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort)))
14 throw std::runtime_error("Failed with plain sort");
Тестовая задача #1
С параллельной политикой
1 //This includes should be from ${T_LUTZ_ROOT}/include
2 #include <numeric>
3 #include <experimental/algorithm>
4
5 /* --- */
6
7 vecToSort = vec;
8 {
9 Stopwatch sw("par sort", baseDuration);
10 sort(std::experimental::parallel::par,
11 std::begin(vecToSort), std::end(vecToSort));
12 }
13 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort)))
14 throw std::runtime_error("Failed with plain sort");
Тестовая задача #1
С последовательной политикой
1 #include "hpx/hpx_init.hpp"
2 #include "hpx/hpx.hpp"
3
4 #include "hpx/parallel/numeric.hpp"
5 #include "hpx/parallel/algorithm.hpp"
6
7 /* --- */
8
9 vecToSort = vec;
10 {
11 Stopwatch sw("seq sort", baseDuration);
12 hpx::parallel::sort(hpx::parallel::seq,
13 std::begin(vecToSort), std::end(vecToSort));
14 }
15 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort)))
16 throw std::runtime_error("Failed with seq sort");
Тестовая задача #1
С параллельной политикой
1 #include "hpx/hpx_init.hpp"
2 #include "hpx/hpx.hpp"
3
4 #include "hpx/parallel/numeric.hpp"
5 #include "hpx/parallel/algorithm.hpp"
6
7 /* --- */
8
9 vecToSort = vec;
10 {
11 Stopwatch sw("par sort", baseDuration);
12 hpx::parallel::sort(hpx::parallel::par,
13 std::begin(vecToSort), std::end(vecToSort));
14 }
15 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort)))
16 throw std::runtime_error("Failed with par sort");
Тестовая задача #1
С параллельной и векторизованной политикой
1 #include "hpx/hpx_init.hpp"
2 #include "hpx/hpx.hpp"
3
4 #include "hpx/parallel/numeric.hpp"
5 #include "hpx/parallel/algorithm.hpp"
6
7 /* --- */
8
9 vecToSort = vec;
10 {
11 Stopwatch sw("par_vec sort", baseDuration);
12 hpx::parallel::sort(hpx::parallel::par_vec,
13 std::begin(vecToSort), std::end(vecToSort));
14 }
15 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort)))
16 throw std::runtime_error("Failed with par_vec sort");
Тестовая задача #2
Обычная реализация
1 const size_t numParts = std::thread::hardware_concurrency()*2 > 0 ?
2 std::thread::hardware_concurrency() * 2 : 8;
3 std::list<std::vector<size_t>> listOfVecs;
4 listOfVecs.resize(numParts);
5 std::generate(listOfVecs.begin(),
6 listOfVecs.end(),
7 [&](){ return makeShuffledVector(memoryToAlloc/numParts);}
8 );
9 double baseDuration = 0;
10 auto list = listOfVecs;
11 {
12 Stopwatch sw("plain for, plain sort");
13 for(auto &vecToSort : list)
14 std::sort(std::begin(vecToSort), std::end(vecToSort));
15 baseDuration = sw.duration();
16 }
17 for(const auto &vecToSort : list)
18 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort)))
19 throw std::runtime_error("Failed with plain for, plain sort");
Тестовая задача #2
Последовательный for, параллельный sort
1 for(auto &vecToSort : list)
2 sort(std::experimental::parallel::par,
3 std::begin(vecToSort), std::end(vecToSort));
4
5 /* --- */
6
7 for(auto &vecToSort : list)
8 hpx::parallel::sort(hpx::parallel::par,
9 std::begin(vecToSort),
10 std::end(vecToSort));
Тестовая задача #2
Параллельный for, последовательный sort
1 for_each(std::experimental::parallel::par,
2 std::begin(list), std::end(list),
3 [](std::vector<size_t> &vecToSort){
4 std::sort(std::begin(vecToSort), std::end(vecToSort));
5 });
6
7 /* --- */
8
9 hpx::parallel::for_each(hpx::parallel::par,
10 std::begin(list), std::end(list),
11 [](std::vector<size_t> &vecToSort){
12 std::sort(std::begin(vecToSort), std::end(vecToSort));
13 });
Тестовая задача #2
Параллельный for, параллельный sort
[параллельный в квадрате, квадратно параллельный]
1 for_each(std::experimental::parallel::par,
2 std::begin(list), std::end(list),
3 [](std::vector<size_t> &vecToSort){
4 sort(std::experimental::parallel::par,
5 std::begin(vecToSort), std::end(vecToSort));
6 });
7
8 /* --- */
9
10 hpx::parallel::for_each(hpx::parallel::par,
11 std::begin(list), std::end(list),
12 [](std::vector<size_t> &vecToSort){
13 hpx::parallel::sort(hpx::parallel::par,
14 std::begin(vecToSort), std::end(vecToSort));
15 });
Результаты
[2 физических, 4 h-threading ядра]
Тест #1
Реализация Политика Ускорение
t-lutz
seq 1
par 2.37
HPX
seq 0.99
par 2.61
par_vec 2.64
Тест #2
Реализация Политика for Политика sort Ускорение
t-lutz
seq par 2.26
par seq 2.78
par par 2.48
HPX
seq par 2.52
par seq 2.75
par par 2.87
Race!
Догнать и перегнать!
1 for(auto &vecToSort : list)
2 std::sort(std::begin(vecToSort), std::end(vecToSort));
3
4 /* --- */
5
6 for_each(std::experimental::parallel::par,
7 std::begin(list), std::end(list),
8 [](std::vector<size_t> &vecToSort){
9 sort(std::experimental::parallel::par,
10 std::begin(vecToSort), std::end(vecToSort));
Race!
1 auto work=[](decltype(list.end()) begin,decltype(list.end()) end){
2 for(auto it = begin; it != end; ++it)
3 std::sort(it->begin(), it->end());
4 };
5 size_t hc = std::thread::hardware_concurrency();
6 if(hc == 0) hc = 8;
7 auto numThreads = std::min(list.size(), hc);
8 auto chunkPerThread = list.size() / numThreads;
9 auto threadBegin = list.begin();
10 auto threadEnd = threadBegin;
11 std::advance(threadEnd, chunkPerThread);
12 std::list<std::future<void>> futures;
13 for(size_t thId = 0; thId < numThreads - 1; ++thId){
14 futures.push_back(std::async(std::launch::async,
15 work, threadBegin, threadEnd));
16 threadBegin = threadEnd;
17 std::advance(threadEnd, chunkPerThread);
18 }
19 work(threadBegin, list.end());
20 for(auto &f : futures) f.get();
И победителем стал...
[2 физических, 4 h-threading ядра]
Тест #2
Реализация Политика Ускорение Количество строк
Parallel STL par/par ∼2.5 2
mine async/seq ∼2.5 20
Динамические политики
1 std::experimental::parallel::execution_policy outerPolicy =
2 std::experimental::parallel::seq;
3 std::experimental::parallel::execution_policy innerPolicy =
4 std::experimental::parallel::par;
5
6 /* Decide at runtime which policy should be */
7 outerPolicy = std::experimental::parallel::par;
8 innerPolicy = std::experimental::parallel::par_vec;
9
10 for_each(outerPolicy,
11 std::begin(list), std::end(list),
12 [&innerPolicy](std::vector<size_t> &vecToSort){
13 sort(innerPolicy,
14 std::begin(vecToSort),
15 std::end(vecToSort));
16 });
Если что-то пошло не так
1 struct Processor
2 {
3 void doWork(size_t id) {
4 throw std::runtime_error("`o´o_ from " + std::to_string(id));
5 }
6 };
7
8 std::vector<Processor> processors;
9 processors.resize(25);
10
11 try {
12 std::cout << "Plain for" << std::endl;
13 std::for_each(processors.begin(), processors.end(),
14 [&](Processor &p){
15 p.doWork(&p - processors.data());
16 });
17 }
18 catch(std::exception &e) {
19 std::cout << e.what() << std::endl;
20 }
Ловим исключения
1 try {
2 std::cout << "Seq for" << std::endl;
3 hpx::parallel::for_each(hpx::parallel::seq,
4 processors.begin(), processors.end(),
5 [&](Processor &p){
6 p.doWork(&p - processors.data());
7 });
8 }
9 catch(hpx::parallel::exception_list &list) {
10 std::cout << "Exception list what: " << list.what() << std::endl;
11 std::cout << "Total " << list.size() << " exceptions:" << std::
endl;
12 for(auto &e : list) {
13 try{ boost::rethrow_exception(e); }
14 catch(std::exception &e){
15 std::cout << "twhat: " << e.what() << std::endl;
16 }
17 }
18 }
19 catch(std::exception &e){
20 std::cout << e.what() << std::endl;
21 }
Ловим исключения
Plain for
`o_´o from 0
Seq for
Exception list what: HPX(unknown_error)
Total 1 exceptions:
what: HPX(unknown_error)
Par for
Exception list what: HPX(unknown_error)
Total 13 exceptions:
what: `o_´o from 0
what: `o_´o from 2
what: `o_´o from 4
what: `o_´o from 6
what: `o_´o from 8
what: `o_´o from 10
what: `o_´o from 12
what: `o_´o from 14
what: `o_´o from 16
what: `o_´o from 18
what: `o_´o from 20
what: `o_´o from 22
what: `o_´o from 24
На десерт
Parallelism Extension for STL еще не реализовано в
компиляторах.
1 #include <algorithm>
2
3 std::some_standard_algorythm_with_stl_containers(
4 std::begin(container),
5 std::end(container)
6 );
Но если используется gcc, то...
На десерт
Parallelism Extension for STL еще не реализовано в
компиляторах.
1 #include <algorithm>
2
3 std::some_standard_algorythm_with_stl_containers(
4 std::begin(container),
5 std::end(container)
6 );
Но если используется gcc, то...
1 //OpenMP should be enabled
2
3 #include <parallel/algorithm>
4
5 std::__parallel::some_standard_algorythm_with_stl_containers(
6 std::begin(container),
7 std::end(container)
8 );
Те же самые примеры
1 std::__parallel::sort(std::begin(vecToSort), std::end(vecToSort));
2
3 std::__parallel::for_each(std::begin(list), std::end(list),
4 [](std::vector<size_t> &vecToSort){
5 std::__parallel::sort(std::begin(vecToSort), std::end(
vecToSort));
6 });
7
8 #pragma omp parallel
9 {
10 #pragma omp single
11 {
12 for(auto it = list.begin(); it != list.end(); ++it)
13 #pragma omp task
14 sort(it->begin(), it->end());
15 }
16 }
Результаты
[2 физических, 4 h-threading ядра]
Тест #2
Реализация Политика Ускорение Количество строк
Parallel STL par/par ∼2.5 2
mine (std::async) async/seq ∼2.5 20
Parallel gcc par/par ∼2.5 2
mine (openmp) task/seq ∼2.5 9

Más contenido relacionado

La actualidad más candente

Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMSergey Platonov
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
 
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...Alexey Paznikov
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...Alexey Paznikov
 
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...Alexey Paznikov
 
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...Alexey Paznikov
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Mikhail Matrosov
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...Alexey Paznikov
 
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...Alexey Paznikov
 
Модель памяти C++ - Андрей Янковский, Яндекс
Модель памяти C++ - Андрей Янковский, ЯндексМодель памяти C++ - Андрей Янковский, Яндекс
Модель памяти C++ - Андрей Янковский, ЯндексYandex
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеIlia Shishkov
 
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...Alexey Paznikov
 
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...Alexey Paznikov
 
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...Alexey Paznikov
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Dima Dzuba
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыcorehard_by
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Yandex
 
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Yandex
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода Pavel Tsukanov
 

La actualidad más candente (20)

Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
 
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
 
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
 
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
 
Модель памяти C++ - Андрей Янковский, Яндекс
Модель памяти C++ - Андрей Янковский, ЯндексМодель памяти C++ - Андрей Янковский, Яндекс
Модель памяти C++ - Андрей Янковский, Яндекс
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в форме
 
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
 
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
 
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 

Similar a Parallel STL

Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesPlatonov Sergey
 
Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesPlatonov Sergey
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кодаAndrey Karpov
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Andrey Karpov
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
 
Улучшение качества открытого программного обеспечения с помощью инструментов ...
Улучшение качества открытого программного обеспечения с помощью инструментов ...Улучшение качества открытого программного обеспечения с помощью инструментов ...
Улучшение качества открытого программного обеспечения с помощью инструментов ...Andrey Karpov
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Mikhail Kurnosov
 
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Mikhail Kurnosov
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPMikhail Kurnosov
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPMikhail Kurnosov
 
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестовЮлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестовMskDotNet Community
 
Всё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаВсё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаAndrey Karpov
 
Статический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутСтатический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутAndrey Karpov
 
Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Tatyanazaxarova
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаAndrey Karpov
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Yandex
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1Michael Karpov
 

Similar a Parallel STL (20)

Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templates
 
Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templates
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
Улучшение качества открытого программного обеспечения с помощью инструментов ...
Улучшение качества открытого программного обеспечения с помощью инструментов ...Улучшение качества открытого программного обеспечения с помощью инструментов ...
Улучшение качества открытого программного обеспечения с помощью инструментов ...
 
JavaDay'14
JavaDay'14JavaDay'14
JavaDay'14
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
 
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMP
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMP
 
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестовЮлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестов
 
Всё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаВсё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программиста
 
Статический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутСтатический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минут
 
course js day 2
course js day 2course js day 2
course js day 2
 
Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
 

Parallel STL

  • 1. C++17: параллельная версия стандартных алгоритмов Евгений Крутько e.s.krutko@gmail.com Национальный исследовательский центр "Курчатовский институт" 25.02.2017
  • 2. Эволюция многопоточной работы в C++ Нам нужно выполнить работу асинхронно 1 int main(){ 2 //Here we should use some features to call doWork in parallel 3 doWork(int a); 4 doSomeOtherWork(double t); 5 //Ensure doWork completed 6 return 0; 7 }
  • 3. Давным-давно... ... у нас не было даже стандарта C++11. 1 //Using POSIX API 2 void* makeDoWork(void *arg) { 3 int *a=reinterpret_cast<int*>(arg); 4 doWork(*a); 5 } 6 int main(){ 7 pthread_t thread; 8 int value = 42; 9 pthread_create( 10 &thread, 11 nullptr, 12 makeDoWork, 13 &value); 14 doSomeOtherWork(double t); 15 pthread_join(thread, nullptr); 16 return 0; 17 }
  • 4. Давным-давно... ... у нас не было даже стандарта C++11. 1 //Using Win API 2 DWORD WINAPI makeDoWork(void *arg) { 3 int *a=reinterpret_cast<int*>(arg); 4 doWork(*a); 5 } 6 int main(){ 7 HANDLE thread; 8 int value = 42; 9 thread = CreateThread( 10 NULL, 11 0, 12 makeDoWork, 13 &value, 14 0, 15 NULL 16 ); 17 doSomeOtherWork(double t); 18 WaitForSingleObject(thread, INFINITE); 19 return 0; 20 }
  • 6. Начиная со стандарта C++11 std::thread std::async / std::future 1 int main(int argc, char**argv) { 2 std::thread thread; 3 int value; 4 //Do doWork() in new thread 5 thread = std::thread( 6 doWork, 7 std::ref(value)); 8 //Do someything else in this thread 9 doSomeOtherWork(); 10 //Whait for doWork() finishes 11 thread.join(); 12 return 0; 13 }
  • 7. Начиная со стандарта C++11 std::thread std::async / std::future 1 int main(int argc, char**argv) { 2 int value; 3 //Do doWork() in new thread 4 auto future = std::async( 5 std::launch::async; 6 doWork, 7 std::ref(value)); 8 //Do someything else in this thread 9 doSomeOtherWork(); 10 //Whait for doWork() finishes 11 future.get(); 12 return 0; 13 }
  • 8. Нам и этого мало, хочется еще проще Возможно когда-нибудь :) 1 auto auto(auto auto) { auto; }
  • 9. Нам и этого мало, хочется еще проще Возможно когда-нибудь :) 1 auto auto(auto auto) { auto; } Уже /почти/ в стандарте 1 //Something from <algorythm> 2 std::some_standard_algorythm_with_stl_containers( 3 std::begin(container), 4 std::end(container) 5 ); 6 //The same but with specification of execution policy 7 std::some_standard_algorythm_with_stl_containers( 8 ExecutionPolicy policy, 9 std::begin(container), 10 std::end(container) 11 );
  • 10. Алгоритмы стандартной библиотеки, доступные в параллельном режиме Объявлены в заголовочном файле <algorithm> Пока в стадии TS в заголовочном файле <experimental/algorithm> adjacent_difference adjacent_find all_of any_of copy copy_if copy_n count count_if equal exclusive_scan fill fill_n find find_end find_first_of find_if find_if_not for_each for_each_n generate generate_n includes inclusive_scan inner_product inplace_merge is_heap is_heap_until is_partitioned is_sorted is_sorted_until lexicographical_compare max_element merge min_element minmax_element mismatch move none_of nth_element partial_sort partial_sort_copy partition partition_copy reduce remove remove_copy remove_copy_if remove_if replace replace_copy replace_copy_if replace_if reverse reverse_copy rotate rotate_copy search search_n set_difference set_intersection set_symmetric_difference set_union sort stable_partition stable_sort swap_ranges transform transform_exclusive_scan transform_inclusive_scan transform_reduce uninitialized_copy uninitialized_copy_n uninitialized_fill uninitialized_fill_n unique unique_copy
  • 11. Политики выполнения 1 //Available from <execution_policy> 2 //While in TS stage from <experimental/execution_policy> 3 4 //Plain old sequenced execution 5 constexpr sequential_execution_policy seq{ }; 6 //Parallel execution 7 constexpr parallel_execution_policy par{ }; 8 //Parallel with SIMD instructions 9 constexpr parallel_vector_execution_policy par_vec{ };
  • 12. Политики выполнения 1 //Available from <execution_policy> 2 //While in TS stage from <experimental/execution_policy> 3 4 //Plain old sequenced execution 5 constexpr sequential_execution_policy seq{ }; 6 //Parallel execution 7 constexpr parallel_execution_policy par{ }; 8 //Parallel with SIMD instructions 9 constexpr parallel_vector_execution_policy par_vec{ }; Стрелять себе по ногам теперь можно еще одним изящным способом 1 int a[] = {0,1}; 2 std::vector<int> v; 3 std::for_each(std::par, 4 std::begin(a), 5 std::end(a), 6 [&](int i) { 7 v.push_back(i*2+1); // Error: data race 8 });
  • 13. Дайте две! Как же попробовать? Из документа https://isocpp.org/files/papers/P0024R2.html Microsoft MS ParallelSTL page HPX HPX github Codeplay Sycl github HSA HSA for math science page Thibaut Lutz github NVIDIA github http://github.com/eskrut/ParallelSTL.git
  • 14. Тестовая задача #1 Обычная реализация 1 auto vec = makeShuffledVector(); 2 double baseDuration = 0; 3 4 auto vecToSort = vec; 5 { 6 Stopwatch sw("plain sort"); 7 std::sort(std::begin(vecToSort), std::end(vecToSort)); 8 baseDuration = sw.duration(); 9 } 10 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort))) 11 throw std::runtime_error("Failed with plain sort");
  • 15. Тестовая задача #1 С последовательной политикой 1 //This includes should be from ${T_LUTZ_ROOT}/include 2 #include <numeric> 3 #include <experimental/algorithm> 4 5 /* --- */ 6 7 vecToSort = vec; 8 { 9 Stopwatch sw("seq sort", baseDuration); 10 sort(std::experimental::parallel::seq, 11 std::begin(vecToSort), std::end(vecToSort)); 12 } 13 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort))) 14 throw std::runtime_error("Failed with plain sort");
  • 16. Тестовая задача #1 С параллельной политикой 1 //This includes should be from ${T_LUTZ_ROOT}/include 2 #include <numeric> 3 #include <experimental/algorithm> 4 5 /* --- */ 6 7 vecToSort = vec; 8 { 9 Stopwatch sw("par sort", baseDuration); 10 sort(std::experimental::parallel::par, 11 std::begin(vecToSort), std::end(vecToSort)); 12 } 13 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort))) 14 throw std::runtime_error("Failed with plain sort");
  • 17. Тестовая задача #1 С последовательной политикой 1 #include "hpx/hpx_init.hpp" 2 #include "hpx/hpx.hpp" 3 4 #include "hpx/parallel/numeric.hpp" 5 #include "hpx/parallel/algorithm.hpp" 6 7 /* --- */ 8 9 vecToSort = vec; 10 { 11 Stopwatch sw("seq sort", baseDuration); 12 hpx::parallel::sort(hpx::parallel::seq, 13 std::begin(vecToSort), std::end(vecToSort)); 14 } 15 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort))) 16 throw std::runtime_error("Failed with seq sort");
  • 18. Тестовая задача #1 С параллельной политикой 1 #include "hpx/hpx_init.hpp" 2 #include "hpx/hpx.hpp" 3 4 #include "hpx/parallel/numeric.hpp" 5 #include "hpx/parallel/algorithm.hpp" 6 7 /* --- */ 8 9 vecToSort = vec; 10 { 11 Stopwatch sw("par sort", baseDuration); 12 hpx::parallel::sort(hpx::parallel::par, 13 std::begin(vecToSort), std::end(vecToSort)); 14 } 15 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort))) 16 throw std::runtime_error("Failed with par sort");
  • 19. Тестовая задача #1 С параллельной и векторизованной политикой 1 #include "hpx/hpx_init.hpp" 2 #include "hpx/hpx.hpp" 3 4 #include "hpx/parallel/numeric.hpp" 5 #include "hpx/parallel/algorithm.hpp" 6 7 /* --- */ 8 9 vecToSort = vec; 10 { 11 Stopwatch sw("par_vec sort", baseDuration); 12 hpx::parallel::sort(hpx::parallel::par_vec, 13 std::begin(vecToSort), std::end(vecToSort)); 14 } 15 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort))) 16 throw std::runtime_error("Failed with par_vec sort");
  • 20. Тестовая задача #2 Обычная реализация 1 const size_t numParts = std::thread::hardware_concurrency()*2 > 0 ? 2 std::thread::hardware_concurrency() * 2 : 8; 3 std::list<std::vector<size_t>> listOfVecs; 4 listOfVecs.resize(numParts); 5 std::generate(listOfVecs.begin(), 6 listOfVecs.end(), 7 [&](){ return makeShuffledVector(memoryToAlloc/numParts);} 8 ); 9 double baseDuration = 0; 10 auto list = listOfVecs; 11 { 12 Stopwatch sw("plain for, plain sort"); 13 for(auto &vecToSort : list) 14 std::sort(std::begin(vecToSort), std::end(vecToSort)); 15 baseDuration = sw.duration(); 16 } 17 for(const auto &vecToSort : list) 18 if (! std::is_sorted(std::begin(vecToSort), std::end(vecToSort))) 19 throw std::runtime_error("Failed with plain for, plain sort");
  • 21. Тестовая задача #2 Последовательный for, параллельный sort 1 for(auto &vecToSort : list) 2 sort(std::experimental::parallel::par, 3 std::begin(vecToSort), std::end(vecToSort)); 4 5 /* --- */ 6 7 for(auto &vecToSort : list) 8 hpx::parallel::sort(hpx::parallel::par, 9 std::begin(vecToSort), 10 std::end(vecToSort));
  • 22. Тестовая задача #2 Параллельный for, последовательный sort 1 for_each(std::experimental::parallel::par, 2 std::begin(list), std::end(list), 3 [](std::vector<size_t> &vecToSort){ 4 std::sort(std::begin(vecToSort), std::end(vecToSort)); 5 }); 6 7 /* --- */ 8 9 hpx::parallel::for_each(hpx::parallel::par, 10 std::begin(list), std::end(list), 11 [](std::vector<size_t> &vecToSort){ 12 std::sort(std::begin(vecToSort), std::end(vecToSort)); 13 });
  • 23. Тестовая задача #2 Параллельный for, параллельный sort [параллельный в квадрате, квадратно параллельный] 1 for_each(std::experimental::parallel::par, 2 std::begin(list), std::end(list), 3 [](std::vector<size_t> &vecToSort){ 4 sort(std::experimental::parallel::par, 5 std::begin(vecToSort), std::end(vecToSort)); 6 }); 7 8 /* --- */ 9 10 hpx::parallel::for_each(hpx::parallel::par, 11 std::begin(list), std::end(list), 12 [](std::vector<size_t> &vecToSort){ 13 hpx::parallel::sort(hpx::parallel::par, 14 std::begin(vecToSort), std::end(vecToSort)); 15 });
  • 24. Результаты [2 физических, 4 h-threading ядра] Тест #1 Реализация Политика Ускорение t-lutz seq 1 par 2.37 HPX seq 0.99 par 2.61 par_vec 2.64 Тест #2 Реализация Политика for Политика sort Ускорение t-lutz seq par 2.26 par seq 2.78 par par 2.48 HPX seq par 2.52 par seq 2.75 par par 2.87
  • 25. Race! Догнать и перегнать! 1 for(auto &vecToSort : list) 2 std::sort(std::begin(vecToSort), std::end(vecToSort)); 3 4 /* --- */ 5 6 for_each(std::experimental::parallel::par, 7 std::begin(list), std::end(list), 8 [](std::vector<size_t> &vecToSort){ 9 sort(std::experimental::parallel::par, 10 std::begin(vecToSort), std::end(vecToSort));
  • 26. Race! 1 auto work=[](decltype(list.end()) begin,decltype(list.end()) end){ 2 for(auto it = begin; it != end; ++it) 3 std::sort(it->begin(), it->end()); 4 }; 5 size_t hc = std::thread::hardware_concurrency(); 6 if(hc == 0) hc = 8; 7 auto numThreads = std::min(list.size(), hc); 8 auto chunkPerThread = list.size() / numThreads; 9 auto threadBegin = list.begin(); 10 auto threadEnd = threadBegin; 11 std::advance(threadEnd, chunkPerThread); 12 std::list<std::future<void>> futures; 13 for(size_t thId = 0; thId < numThreads - 1; ++thId){ 14 futures.push_back(std::async(std::launch::async, 15 work, threadBegin, threadEnd)); 16 threadBegin = threadEnd; 17 std::advance(threadEnd, chunkPerThread); 18 } 19 work(threadBegin, list.end()); 20 for(auto &f : futures) f.get();
  • 27. И победителем стал... [2 физических, 4 h-threading ядра] Тест #2 Реализация Политика Ускорение Количество строк Parallel STL par/par ∼2.5 2 mine async/seq ∼2.5 20
  • 28. Динамические политики 1 std::experimental::parallel::execution_policy outerPolicy = 2 std::experimental::parallel::seq; 3 std::experimental::parallel::execution_policy innerPolicy = 4 std::experimental::parallel::par; 5 6 /* Decide at runtime which policy should be */ 7 outerPolicy = std::experimental::parallel::par; 8 innerPolicy = std::experimental::parallel::par_vec; 9 10 for_each(outerPolicy, 11 std::begin(list), std::end(list), 12 [&innerPolicy](std::vector<size_t> &vecToSort){ 13 sort(innerPolicy, 14 std::begin(vecToSort), 15 std::end(vecToSort)); 16 });
  • 29. Если что-то пошло не так 1 struct Processor 2 { 3 void doWork(size_t id) { 4 throw std::runtime_error("`o´o_ from " + std::to_string(id)); 5 } 6 }; 7 8 std::vector<Processor> processors; 9 processors.resize(25); 10 11 try { 12 std::cout << "Plain for" << std::endl; 13 std::for_each(processors.begin(), processors.end(), 14 [&](Processor &p){ 15 p.doWork(&p - processors.data()); 16 }); 17 } 18 catch(std::exception &e) { 19 std::cout << e.what() << std::endl; 20 }
  • 30. Ловим исключения 1 try { 2 std::cout << "Seq for" << std::endl; 3 hpx::parallel::for_each(hpx::parallel::seq, 4 processors.begin(), processors.end(), 5 [&](Processor &p){ 6 p.doWork(&p - processors.data()); 7 }); 8 } 9 catch(hpx::parallel::exception_list &list) { 10 std::cout << "Exception list what: " << list.what() << std::endl; 11 std::cout << "Total " << list.size() << " exceptions:" << std:: endl; 12 for(auto &e : list) { 13 try{ boost::rethrow_exception(e); } 14 catch(std::exception &e){ 15 std::cout << "twhat: " << e.what() << std::endl; 16 } 17 } 18 } 19 catch(std::exception &e){ 20 std::cout << e.what() << std::endl; 21 }
  • 31. Ловим исключения Plain for `o_´o from 0 Seq for Exception list what: HPX(unknown_error) Total 1 exceptions: what: HPX(unknown_error) Par for Exception list what: HPX(unknown_error) Total 13 exceptions: what: `o_´o from 0 what: `o_´o from 2 what: `o_´o from 4 what: `o_´o from 6 what: `o_´o from 8 what: `o_´o from 10 what: `o_´o from 12 what: `o_´o from 14 what: `o_´o from 16 what: `o_´o from 18 what: `o_´o from 20 what: `o_´o from 22 what: `o_´o from 24
  • 32. На десерт Parallelism Extension for STL еще не реализовано в компиляторах. 1 #include <algorithm> 2 3 std::some_standard_algorythm_with_stl_containers( 4 std::begin(container), 5 std::end(container) 6 ); Но если используется gcc, то...
  • 33. На десерт Parallelism Extension for STL еще не реализовано в компиляторах. 1 #include <algorithm> 2 3 std::some_standard_algorythm_with_stl_containers( 4 std::begin(container), 5 std::end(container) 6 ); Но если используется gcc, то... 1 //OpenMP should be enabled 2 3 #include <parallel/algorithm> 4 5 std::__parallel::some_standard_algorythm_with_stl_containers( 6 std::begin(container), 7 std::end(container) 8 );
  • 34. Те же самые примеры 1 std::__parallel::sort(std::begin(vecToSort), std::end(vecToSort)); 2 3 std::__parallel::for_each(std::begin(list), std::end(list), 4 [](std::vector<size_t> &vecToSort){ 5 std::__parallel::sort(std::begin(vecToSort), std::end( vecToSort)); 6 }); 7 8 #pragma omp parallel 9 { 10 #pragma omp single 11 { 12 for(auto it = list.begin(); it != list.end(); ++it) 13 #pragma omp task 14 sort(it->begin(), it->end()); 15 } 16 }
  • 35. Результаты [2 физических, 4 h-threading ядра] Тест #2 Реализация Политика Ускорение Количество строк Parallel STL par/par ∼2.5 2 mine (std::async) async/seq ∼2.5 20 Parallel gcc par/par ∼2.5 2 mine (openmp) task/seq ∼2.5 9