Taskflow помогает быстро писать параллельные и гетерогенные программы с использованием современного C++
Taskflow быстрее, более выразителен и проще для интеграции, чем многие существующие фреймворки для программирования задач, при работе с сложными параллельными нагрузками.
Taskflow позволяет быстро реализовать стратегии декомпозиции задач, которые включают как регулярные, так и нерегулярные вычислительные модели, а также эффективный scheduler с механизмом работы-отбора для оптимизации многопоточной производительности.
Статическая задачная модель | Задачная модель субпотока |
---|---|
по управлению потоком выполнения между зависимыми задачами для реализации циклов и условий, | |
которые были трудны для реализации с помощью существующих инструментов. | Условная задачная модель |
:-----------------: | |
Taskflow является композиционным. Вы можете создавать большие параллельные графы через компоновку модульных и повторно используемых блоков, которые легче оптимизировать в рамках отдельной области.
Композиция графов задач |
---|
Taskflow поддерживает гетерогенную задачную модель для ускорения широкого спектра приложений научных вычислений за счет использования мощности совместной вычислительной работы CPU-GPU.| Параллельное выполнение задач на CPU и GPU |
| :-----------------: |
| |
Taskflow предоставляет визуализацию и инструменты для профилирования программ на Taskflow.
Профилировщик Taskflow |
---|
![]() |
Мы привержены поддержке надежных разработок как для академических, так и для промышленных исследовательских проектов в области параллельных вычислений. Узнайте, кто использует Taskflow, и что говорят наши пользователи:+ "Taskflow — это самый чистый API задач, который я когда-либо видел." Джеймс Хокинг @Corelium Inc
Ниже приведен пример программы (simple.cpp
), которая создает четыре задачи
A
, B
, C
и D
, где A
выполняется перед B
и C
, а D
выполняется после B
и C
.
Когда A
завершается, B
и C
могут выполняться параллельно.
Попробуйте его в действии на Compiler Explorer (godbolt)!
#include <taskflow/taskflow.hpp> // Taskflow является заголовочным файлом
int main(){
tf::Executor executor;
tf::Taskflow taskflow;
auto [A, B, C, D] = taskflow.emplace( // создаем четыре задачи
[] () { std::cout << "TaskA\n"; },
[] () { std::cout << "TaskB\n"; },
[] () { std::cout << "TaskC\n"; },
[] () { stdь cout << "TaskD\n"; }
);
A.precede(B, C); // A выполняется перед B и C
D.succeed(B, C); // D выполняется после B и C
executor.run(taskflow).wait();
}
Taskflow является только заголовочным и нет необходимости в установке. Чтобы скомпилировать программу, клонируйте проект Taskflow и укажите компилятору включить заголовочные файлы.
~$ git clone https://github.com/taskflow/taskflow.git # клонировать только один раз
~$ g++ -std=c++20 examples/simple.cpp -I. -O2 -pthread -o simple
~$ ./simple
TaskA
TaskC
TaskB
TaskD
TFProf, чтобы вы могли профилировать и визуализировать программы Taskflow в удобном для использования веб-интерфейсе.
# запустите программу с переменной окружения TF_ENABLE_PROFILER включенной
~$ TF_ENABLE_PROFILER=simple.json ./simple
~$ cat simple.json
[
{"executor":"0","data":[{"worker":0,"level":0,"data":[{"span":[172,186],"name":"0_0","type":"static"},{"span":[187,189],"name":"0_1","type":"static"}]},{"worker":2,"level":0,"data":[{"span":[93,164],"name":"2_0","type":"static"},{"span":[170,179],"name":"2_1","type":"static"}]}]}
]
# вставьте данные профайлинга в формате JSON на https://taskflow.github.io/tfprof/
Кроме диаграммы выполнения, вы можете экспортировать граф в формат DOT и визуализировать его с помощью различных бесплатных [инструментов GraphViz][GraphViz].
// экспортируйте граф задач в формат DOT через std::cout
taskflow.dump(std::cout);
Taskflow предоставляет пользователям возможность создания как статических, так и динамических графов задач для выражения параллелизма от начала до конца в графе задач, который включает внутренний контрольный поток.1. Создание подграфа задач 2. Интеграция контрольного потока в граф задач 3. Передача задачи на GPU 4. Составление графов задач 5. Запуск асинхронных задач 6. Выполнение Taskflow 7. Использование стандартных параллельных алгоритмов## Создание подграфа задач
Taskflow поддерживает динамическое выполнение задач для создания подграфа задач из выполнения задачи для реализации динамического параллелизма. В следующей программе создается граф зависимости задач, родителем которого является задача B
.
tf::Задача A = taskflow.emplace([](){}).name("A");
tf::Задача C = taskflow.emplace([](){}).name("C");
tf::Задача D = taskflow.emplace([](){}).name("D");
tf::Задача B = taskflow.emplace([] (tf::Подпоток& подпоток) {
tf::Задача B1 = подпоток.emplace([](){}).name("B1");
tf::Задача B2 = подпоток.emplace([](){}).name("B2");
tf::Задача B3 = подпоток.emplace([](){}).name("B3");
B3.succeed(B1, B2); // B3 выполняется после B1 и B2
}).name("B");
A.precede(B, C); // A выполняется перед B и C
D.succeed(B, C); // D выполняется после B и C
Taskflow поддерживает условное выполнение задач для быстрого внедрения управления потоком между зависимыми задачами для реализации циклов и условий в полной графе задач.
tf::Задача init = taskflow.emplace([](){}).name("init");
tf::Задача stop = taskflow.emplace([](){}).name("stop");
// создает условную задачу, которая возвращает случайное двоичное значение
tf::Задача cond = taskflow.emplace(
[](){ return std::rand() % 2; }
).name("cond");
init.precede(cond);
// создает обратную связь {0: cond, 1: stop}
cond.precede(cond, stop);
__global__ void saxpy(size_t N, float alpha, float* dx, float* dy) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < N) {
dy[i] = alpha * dx[i] + dy[i];
}
}
// создает задачу CUDA Graph
tf::Задача cudaflow = taskflow.emplace([&]() {
tf::cudaGraph cg;
tf::cudaTask h2d_x = cg.copy(dx, hx.data(), N);
tf::cudaTask h2d_y = cg.copy(dy, hy.data(), N);
tf::cudaTask d2h_x = cg.copy(hx.data(), dx, N);
tf::cudaTask d2h_y = cg.copy(hy.data(), dy, N);
tf::cudaTask saxpy = cg.kernel((N + 255) / 256, 256, 0, saxpy, N, 2.0f, dx, dy);
saxpy.succeed(h2d_x, h2d_y)
.precede(d2h_x, d2h_y);
// создает исполняемый граф CUDA и запускает его через поток
tf::cudaGraphExec exec(cg);
tf::cudaStream stream;
stream.run(exec).synchronize();
}).name("CUDA Graph Task");
Taskflow является композиционной системой. Вы можете создавать большие параллельные графы через композицию модульных и перезапускаемых блоков, которые легче оптимизировать в отдельных областях.
tf::Taskflow f1, f2;
// создаем граф задач f1 из двух задач
tf::Task f1A = f1.emplace([]() { std::cout << "Задача f1A\n"; })
.name("f1A");
tf::Task f1B = f1.emplace([]() { std::cout << "Задача f1B\n"; })
.name("f1B");
// создаем граф задач f2 с одним модульным блоком, состоящим из f1
tf::Task f2A = f2.emplace([]() { std::cout << "Задача f2A\n"; })
.name("f2A");
tf::Task f2B = f2.emplace([]() { std::cout << "Задача f2B\n"; })
.name("f2B");
tf::Task f2C = f2.emplace([]() { std::cout << "Задача f2C\n"; })
.name("f2C");
``````cpp
tf::Task f1_module_task = f2.composed_of(f1)
.name("модуль");
f1_module_task.succeed(f2A, f2B)
.precede(f2C);
Taskflow поддерживает асинхронное выполнение задач. Вы можете запускать задачи асинхронно для динамического исследования параллелизма графа задач.
tf::Executor executor;
// создаем асинхронные задачи напрямую из исполнителя
std::future<int> future = executor.async([](){
std::cout << "асинхронная задача возвращает 1\n";
return 1;
});
executor.silent_async([](){ std::cout << "асинхронная задача не возвращает значение\n"; });
// создаем асинхронные задачи с динамическими зависимостями
tf::AsyncTask A = executor.silent_dependent_async([](){ printf("A\n"); });
tf::AsyncTask B = executor.silent_dependent_async([](){ printf("B\n"); }, A);
tf::AsyncTask C = executor.silent_dependent_async([](){ printf("C\n"); }, A);
tf::AsyncTask D = executor.silent_dependent_async([](){ printf("D\n"); }, B, C);
executor.wait_for_all();
Исполнитель предоставляет несколько потокобезопасных методов для выполнения графа задач.
Вы можете запускать граф задач один раз, несколько раз или до достижения остановочного критерия.
Эти методы являются неблокирующими с возвращением tf::Future<void>
, чтобы позволить вам проверять статус выполнения.
// запускает граф задач один раз
tf::Future<void> run_once = executor.run(taskflow); // ожидание завершения этого запуска
run_once.get();
// выполнение потокового процесса четыре раза
executor.run_n(taskflow, 4);
```// выполнение потокового процесса пять раз
executor.run_until(taskflow, [counter=5]() { return --counter == 0; });
// блокировка исполнителя до завершения всех субмитированных потоковых процессов
executor.wait_for_all();
## Использование стандартных параллельных алгоритмов
Taskflow определяет алгоритмы для быстрого выражения общих параллельных шаблонов с использованием стандартных синтаксисов C++, таких как параллельные итерации, параллельные свёртки и параллельная сортировка.
```cpp
tf::Task task1 = taskflow.for_each( // присваивает каждому элементу значение 100 параллельно
first, last, [] (auto& i) { i = 100; }
);
tf::Task task2 = taskflow.reduce( // свёртывает диапазон элементов параллельно
first, last, init, [] (auto a, auto b) { return a + b; }
);
tf::Task task3 = taskflow.sort( // сортирует диапазон элементов параллельно
first, last, [] (auto a, auto b) { return a < b; }
);
Кроме того, Taskflow предоставляет композиционные блоки построения графа для эффективной реализации общих параллельных алгоритмов, таких как параллельная конвейерная линия.
// создание конвейерной линии для передачи пяти токенов через три последовательные стадии
tf::Pipeline pl(num_parallel_lines,
tf::Pipe{tf::PipeType::SERIAL, [](tf::Pipeflow& pf) {
if(pf.token() == 5) {
pf.stop();
}
}},
tf::Pipe{tf::PipeType::SERIAL, [](tf::Pipeflow& pf) {
printf("stage 2: input buffer[%zu] = %d\n", pf.line(), buffer[pf.line()]);
}},
tf::Pipe{tf::PipeType::SERIAL, [](tf::Pipeflow& pf) {
printf("stage 3: input buffer[%zu] = %d\n", pf.line(), buffer[pf.line()]);
}}
);
taskflow.composed_of(pl)
executor.run(taskflow).wait();
```# Поддерживаемые компиляторы
Для использования Taskflow вам нужен компилятор, поддерживающий C++17:
+ GNU C++ Compiler версии не менее 8.4 с флагом `-std=c++17`
+ Clang C++ Compiler версии не менее 6.0 с флагом `-std=c++17`
+ Microsoft Visual Studio версии не менее 19.14 с флагом `/std:c++17`
+ AppleClang Xcode версии не менее 12.0 с флагом `-std=c++17`
+ Nvidia CUDA Toolkit и Compiler (nvcc) версии не менее 11.1 с флагом `-std=c++17`
+ Intel C++ Compiler версии не менее 19.0.1 с флагом `-std=c++17`
+ Intel DPC++ Clang Compiler версии не менее 13.0.0 с флагом `-std=c++17` и SYCL20
Taskflow работает на Linux, Windows и Mac OS X.
Хотя Taskflow в основном поддерживает C++17, вы можете включить компиляцию C++20 через флаг `-std=c++20` (или `/std:c++20` для MSVC) для достижения лучшей производительности благодаря новым возможностям C++20.
# Узнайте больше о Taskflow
Посетите наш [сайт проекта][Project Website] и [документацию][documentation], чтобы узнать больше о Taskflow. Чтобы включиться:
+ Посмотрите [заметки о выпусках][release notes], чтобы быть в курсе новых версий
+ Прочитайте пошаговое руководство в [кулинарной книге][cookbook]
+ Отправьте проблему на [GitHub issues][GitHub issues]
+ Узнайте наши технические детали на [ссылках][references]
+ Посмотрите наши технические доклады на YouTube
| [CppCon20 Технический Доклад][cppcon20 talk] | [MUC++ Технический Доклад](https://www.youtube.com/watch?v=u8Mc_WgGwVY) |
| :------------: | :-------------: |
|  | <img align="right" src="doxygen/images/muc++20-thumbnail.jpg" width="100%"> |Мы привержены поддержке надежных разработок для академических и промышленных исследовательских проектов параллельных и гетерогенных вычислений.
Если вы используете Taskflow, пожалуйста, цитируйте следующую статью, опубликованную в IEEE TPDS 2021:
+ Tsung-Wei Huang, Dian-Lun Lin, Chun-Xun Lin, и Yibo Lin, "Taskflow: Легковесная система параллельных и гетерогенных вычислений графа задач", <i>IEEE Transactions on Parallel and Distributed Systems (TPDS)</i>, том 33, номер 6, стр. 1303–1320, июнь 2022
Более важно, мы ценим всех [вкладчиков Taskflow][contributors] и следующие организации за спонсирование проекта Taskflow!
| | | | |
|:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------:|
|<img src="doxygen/images/utah-ece-logo.png">|<img src="doxygen/images/nsf.png"> | <img src="doxygen/images/darpa.png"> | <img src="doxygen/images/NumFocus.png">|
|<img src="doxygen/images/nvidia-logo.png"> | <img src="doxygen/images/uw-madison-ece-logo.png"> | | |
# Лицензия
Taskflow лицензирован с [лицензией MIT](./LICENSE).
Вы полностью свободны в распространении вашей работы, основанной на Taskflow.* * *[Цзян Вэй Хуанг]: https://tsung-wei-huang.github.io/
[Релизы GitHub]: https://github.com/taskflow/taskflow/releases
[Проблемы GitHub]: https://github.com/taskflow/taskflow/issues
[Инсайты GitHub]: https://github.com/taskflow/taskflow/pulse
[Запросы на слияние GitHub]: https://github.com/taskflow/taskflow/pulls
[GraphViz]: https://www.graphviz.org/
[Сайт проекта]: https://taskflow.github.io/
[cppcon20]: https://www.youtube.com/watch?v=MX15huP5DsM
[Конtributors]: https://taskflow.github.io/taskflow/contributors.html
[Totalgee]: https://github.com/totalgee
[NSF]: https://www.nsf.gov/
[UIUC]: https Yöntem=https://illinois.edu/
[CSL]: https://csl.illinois.edu/
[UofU]: https://www.utah.edu/
[Документация]: https://taskflow.github.io/taskflow/index.html
[Примечания к выпускам]: https://taskflow.github.io/taskflow/Releases.html
[Кулинарная книга]: https://taskflow.github.io/taskflow/pages.html
[Ссылки]: https://taskflow.github.io/taskflow/References.html
[PayMe]: https://www.paypal.me/twhuang/10
[Почта]: mailto:twh760812@gmail.com
[Cpp Conference 2018]: https://github.com/CppCon/CppCon2018
[TPDS22]: https://tsung-wei-huang.github.io/papers/tpds21-taskflow.pdf
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )