1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/mirrors-cpp-taskflow

Клонировать/Скачать
README.md 25 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 19.06.2025 18:02 7a816d1

Очередность задач

Ubuntu macOS Windows [Wiki][documentation] TFProf [Цитирование][TPDS22]

Taskflow помогает быстро писать параллельные и гетерогенные программы с использованием современного C++

Почему Taskflow?

Taskflow быстрее, более выразителен и проще для интеграции, чем многие существующие фреймворки для программирования задач, при работе с сложными параллельными нагрузками.

Taskflow позволяет быстро реализовать стратегии декомпозиции задач, которые включают как регулярные, так и нерегулярные вычислительные модели, а также эффективный scheduler с механизмом работы-отбора для оптимизации многопоточной производительности.

Статическая задачная модель Задачная модель субпотока
по управлению потоком выполнения между зависимыми задачами для реализации циклов и условий,
которые были трудны для реализации с помощью существующих инструментов. Условная задачная модель
:-----------------:

Taskflow является композиционным. Вы можете создавать большие параллельные графы через компоновку модульных и повторно используемых блоков, которые легче оптимизировать в рамках отдельной области.

Композиция графов задач

Taskflow поддерживает гетерогенную задачную модель для ускорения широкого спектра приложений научных вычислений за счет использования мощности совместной вычислительной работы CPU-GPU.| Параллельное выполнение задач на CPU и GPU | | :-----------------: | | |

Taskflow предоставляет визуализацию и инструменты для профилирования программ на Taskflow.

Профилировщик Taskflow

Мы привержены поддержке надежных разработок как для академических, так и для промышленных исследовательских проектов в области параллельных вычислений. Узнайте, кто использует Taskflow, и что говорят наши пользователи:+ "Taskflow — это самый чистый API задач, который я когда-либо видел." Джеймс Хокинг @Corelium Inc

  • "Taskflow имеет очень простое и элегантное представление задач. Высокая производительность также хорошо масштабируется." [Глен Фрэзер][totalgee]
  • "Taskflow позволяет мне эффективно управлять параллельным процессированием." Хаябуса @Обучение
  • "Taskflow увеличивает пропускную способность нашего графического движка всего за несколько часов работы." Жан-Мишель @KDAB
  • "Лучший постер для открытой библиотеки параллельных вычислений." [Конференция Cpp 2018][Cpp Conference 2018]
  • *"Второе место в конкурсе на лучшее открытое программное обеспечение." Конференция ACM Multimedia 2019*Увидеть краткий презентационный материал и посетить [документацию][documentation], чтобы узнать больше о Taskflow. Технические детали можно найти в нашей [статье IEEE TPDS][TPDS22].

Напишите свой первый программу на Taskflow

Ниже приведен пример программы (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

Визуализация вашего первого программы TaskflowTaskflow включает встроенный профайлер,

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);

Перенос задачи на GPUTaskflow поддерживает выполнение задач на GPU для ускорения широкого спектра приложений научных вычислений с использованием технологии совместной работы CPU-GPU от Nvidia CUDA Graph.

__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) |
| :------------: | :-------------: |
| ![](doxygen/images/cppcon20-thumbnail.jpg) | <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, стр. 13031320, июнь 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 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/mirrors-cpp-taskflow.git
git@api.gitlife.ru:oschina-mirror/mirrors-cpp-taskflow.git
oschina-mirror
mirrors-cpp-taskflow
mirrors-cpp-taskflow
master