Taskflow 是一个现代 C++ 并发任务调度库,专注于表达复杂的任务依赖图(task dependency graphs),并利用高效的工作窃取(work-stealing)调度器在多核 CPU 上实现并行执行。它由 National Tsing Hua University 的研究人员开发,设计目标是兼顾表达力、性能和易用性,尤其适合用于构建 DAG(有向无环图)驱动的并行应用,如机器学习流水线、物理仿真、构建系统、自动化测试等。

GitHub 主页:https://github.com/taskflow/taskflow
文档:https://taskflow.github.io/


一、核心特性

  • Header-only:无外部依赖,仅需包含头文件即可使用。
  • 支持静态与动态任务图
    • 静态图:编译时或初始化时确定结构。
    • 动态图:运行时可动态构建子图(如递归、条件分支)。
  • 高效 work-stealing 调度器:基于 per-thread deque,减少锁竞争。
  • GPU 任务支持(需 CUDA):可调度 CUDA kernel 或流。
  • 条件任务(Condition Task):支持运行时分支(类似 if/else)。
  • 模块化子图(Subflow):可嵌套任务图,实现递归或模块化设计。
  • 性能优于 TBB flow_graph 和 OpenMP task(官方 benchmark 显示)。

二、基础使用示例

#include <taskflow/taskflow.hpp>

int main() {
  tf::Executor executor;
  tf::Taskflow taskflow;

  auto [A, B, C, D] = taskflow.emplace(
    [](){ std::cout << "Task A\n"; },
    [](){ std::cout << "Task B\n"; },
    [](){ std::cout << "Task C\n"; },
    [](){ std::cout << "Task D\n"; }
  );

  A.precede(B, C);  // A → B, A → C
  B.precede(D);     // B → D
  C.precede(D);     // C → D

  executor.run(taskflow).wait();
  return 0;
}

输出顺序保证:A 先执行,B/C 并行执行,D 最后执行。


三、高级用法详解

1. 动态子图(Subflow)

适用于递归、分治、运行时展开的任务结构。

tf::Task parent = taskflow.emplace([&](tf::Subflow& sf) {
  for(int i = 0; i < 4; ++i) {
    sf.emplace([i](){ std::cout << "Dynamic task " << i << "\n"; });
  }
}).name("parent");

Subflow 内部任务会自动并行调度,parent 任务在所有子任务完成后才结束。

✅ 应用场景:并行遍历树、分治 FFT、动态任务生成(如游戏 AI 行为树)。


2. 条件任务(Condition Task)

运行时根据返回值决定下一个执行分支(类似 switch)。

auto cond = taskflow.emplace([]() -> int {
  return rand() % 3;  // 返回 0, 1, 或 2
}).name("cond");

auto t0 = taskflow.emplace([](){ std::cout << "Branch 0\n"; });
auto t1 = taskflow.emplace([](){ std::cout << "Branch 1\n"; });
auto t2 = taskflow.emplace([](){ std::cout << "Branch 2\n"; });

cond.precede(t0, t1, t2);
cond.branch(t0, t1, t2);  // 返回 0→t0, 1→t1, 2→t2

✅ 应用场景:状态机、运行时策略选择、错误恢复路径。


3. GPU 任务(CUDA)

需启用 CUDA 支持(编译时定义 TF_CUDA)。

__global__ void add(int* x, int* y, int* z) {
  *z = *x + *y;
}

tf::Task gpu_task = taskflow.emplace([&] (tf::cudaFlow& cf) {
  int *x, *y, *z;
  cf.memalloc(x, 1);
  cf.memalloc(y, 1);
  cf.memalloc(z, 1);
  cf.memset(x, 2, sizeof(int));
  cf.memset(y, 3, sizeof(int));
  cf.kernel(dim3(1), dim3(1), 0, add, x, y, z);
  // 可加 cf.copy(host_z, z, sizeof(int)) 回传
});

✅ 应用场景:异构计算流水线,CPU-GPU 协同任务图。


4. 任务复用与模块化(Composable Graphs)

通过 composed_of 复用子图:

tf::Taskflow module;
auto m1 = module.emplace([](){ std::cout << "M1\n"; });
auto m2 = module.emplace([](){ std::cout << "M2\n"; });
m1.precede(m2);

tf::Taskflow main;
auto t = main.composed_of(module).name("instance1");
auto u = main.composed_of(module).name("instance2");
t.precede(u);

executor.run(main).wait();

✅ 适用于构建可复用的算法模块(如预处理-求解-后处理流水线)。


5. 性能调优技巧

  • 避免任务粒度过细:每个任务应有足够计算量(> 微秒级),否则调度开销占主导。
  • 使用 tf::Executor(num_threads) 指定线程数:默认为 std::thread::hardware_concurrency()
  • 复用 Executor:创建一次,多次运行不同 Taskflow,避免反复构建线程池。
  • 监控任务图:使用 taskflow.dump(std::cout) 输出 Graphviz 格式进行可视化。

四、与 TBB、OpenMP 对比

特性 Taskflow TBB flow_graph OpenMP task
表达力 ⭐⭐⭐⭐⭐(DAG + 动态 + 条件) ⭐⭐⭐(静态图为主) ⭐⭐(简单依赖)
性能 极高(lock-free work-stealing) 中(依赖 runtime)
GPU 支持 ✅(原生 CUDA) ❌(OpenMP 5.0+ 有,但生态弱)
学习曲线
项目活跃度 高(持续更新) 中(Intel 维护) 高(标准)

✅ 若你需要复杂控制流 + 高性能 + 现代 C++,Taskflow 是目前最推荐的选择。


五、典型应用场景

  • 多阶段仿真流水线:网格生成 → 求解器 → 后处理 → 可视化,各阶段可并行或串行。
  • 参数扫描与优化:每个参数组合是一个子图,并行执行。
  • 构建系统替代:比 Make/Ninja 更灵活地表达依赖。
  • AI 推理流水线:预处理 → 模型推理 → 后处理,支持 CPU/GPU 混合。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐