oneTBB task_arena 并发编程实战解析 mold 仓库内置的 fractal 分形示例【免费下载链接】moldmold: A Modern Linker 项目地址: https://gitcode.com/GitHub_Trending/mo/mold导读fractal 是 oneTBBoneAPI Threading Building Blocks官方示例集中的一个经典并发程序位于本仓库 third-party/tbb/examples/task_arena/fractal 目录下。它以两个不同并发级别并行渲染 Mandelbrot 分形图为载体直观演示了task_arena、task_group、task_group_context、parallel_for与blocked_range2d等核心并行原语的协同用法。读完本文你将掌握该示例的 CMake 构建方式、全部命令行参数语义、控制台与 GUI 两种运行模式以及它背后双 arena 分区限流 活动分形优先调度的并发设计原理可直接迁移到自己的并行渲染或计算任务中。示例概览一个窗口、两个分形、两种并发级别根据该示例的 READMEfractal 示例会计算两个经典的 Mandelbrot 分形且两者使用不同的并发级别concurrency levels。应用程序窗口被划分为左右两个区域分别渲染一个分形示例同时还提供纯控制台模式便于在无图形环境下进行测试与性能测量。从源码 main.cpp 可以看出运行形态的分流逻辑若图形窗口初始化成功默认窗口尺寸为 1024×512见 main.cpp进入交互式 GUI 主循环支持鼠标与键盘实时操作若 GUI 初始化失败则回退到控制台模式此时帧数固定为 1num_frames num_frames 0 ? 1 : num_frames并会按线程数范围依次跑多轮输出每轮耗时用于对比不同线程数下的扩展性。两个分形的差异不仅体现在渲染区域上更体现在并发资源配额上——这正是该示例讲解task_arena的核心场景详见后文并发设计解析一节。构建示例CMake 两步走示例的构建遵循标准的 CMake 流程使用源码目录下的 CMakeLists.txtcmake path_to_example [EXAMPLES_UI_MODEvalue] cmake --build .其中path_to_example指向本示例目录third-party/tbb/examples/task_arena/fractal。构建产物为名为fractal的可执行文件链接目标为TBB::tbb、Threads::Threads以及由公共 GUI 子目录生成的UI_LIB_fractal见 CMakeLists.txt因此示例同时依赖 oneTBB 运行时与平台图形库。EXAMPLES_UI_MODE选择界面后端构建时可通过 CMake 变量EXAMPLES_UI_MODE指定 GUI 实现方式支持的值如下表依据本示例 README 及 examples/README.md 归纳平台支持值说明Windows*gdiGDI 实现对应公共目录中的 gdivideo.cppWindows*d2dDirect 2D 实现性能可能更优但要求系统已安装 Microsoft* DirectX* SDK需定义DXSDK_DIRLinux*xX11 实现对应 xvideo.cpp可能需要libXext才能正确显示macOS*macOpenGL 实现要求可用Foundation与Cocoa库对应 macvideo.cpp全平台con控制台模式默认值对应 convideo.cpp默认模式为con。例如在 Linux 无图形终端上显式选择控制台模式cmake third-party/tbb/examples/task_arena/fractal -DEXAMPLES_UI_MODEcon cmake --build .提示本仓库将 oneTBB 以第三方依赖形式内置在 third-party/tbb 中fractal 示例属于该依赖自带的官方代码样例构建时需要保证 oneTBB 库本身已可用CMake 通过 FindTBB.cmake 定位。运行示例三个预定义 make 目标示例的 CMakeLists.txt 通过add_execution_target注册了三个便捷执行目标对应 README 中描述的 make targetsmake 目标等价命令参数用途make run_fractalfractal auto以默认参数执行用于快速体验make perf_run_fractalfractal auto 1 1000000 silent建议的性能测量参数auto 线程数、1 帧、最大 100 万次迭代、静默输出make light_test_fractalfractal auto 1 1000轻量冒烟测试auto 线程数、1 帧、最大 1000 次迭代缩短执行时间这三个目标展示了如何用命令行参数控制工作负载规模性能测量时提高迭代上限1000000并加silent只保留耗时输出快速测试时压低迭代上限1000换取秒级完成。在 GUI 模式下make run_fractal会打开分形窗口并进入交互循环。命令行参数详解fractal 的完整用法如下摘自 READMEfractal [n-of-threadsvalue] [n-of-framesvalue] [max-of-iterationsvalue] [grain-sizevalue] [use-auto-partitioner] [silent] [single] [-h] [n-of-threads [n-of-frames [max-of-iterations [grain-size]]]]参数按位置依次解释参数含义默认值/约束-h打印命令行选项帮助—n-of-threads使用的线程数可写low[:high]区间或auto平台默认值默认来自utility::get_default_num_threads见 main.cpplow、high为非负整数n-of-frames示例内部处理的帧数默认-1控制台模式下被修正为 1见 main.cppmax-of-iterations分形最大迭代次数默认 1,000,000见 main.cppgrain-size可选的分块粒度必须为正整数默认 8见 main.cpp对应blocked_range2d的每个维度的分块大小use-auto-partitioner使用oneapi::tbb::auto_partitioner代替默认的simple_partitioner默认关闭schedule_autofalsesilent除耗时外不输出任何内容默认关闭single只处理一个分形不创建第二个分形默认关闭参数解析由公共工具 utility.hpp 中的parse_cli_arguments完成前四个位置参数、三个开关参数依次绑定-h隐式可用见 main.cpp。n-of-threads 的区间语法n-of-threads是示例中最值得细看的参数。它并非简单整数而是一个thread_number_range结构定义于 utility.hpp支持low[:high[:(|*|#)step]]语法auto解析为平台默认线程数value auto ? auto_value : ...见 utility.hpp单个整数N等价于N:N只跑一个线程档位区间low:high控制台模式下会从low到high依次遍历步进默认采用step_function_power2_ladder即按 2 的幂阶梯递增见 utility.hpp每档跑一轮并分别计时可选的三段式low:high:step可显式指定步进函数、*、#前缀分别对应加性、乘性等步进策略。在 GUI 模式下threads.first另有含义大于 0 表示使用独立的事件/更新循环线程threads.second则作为调度器初始化时的线程数见 main.cpp 注释。控制台模式下threads.first与threads.last则纯粹用于多档扫描main.cpp。并发设计解析双 arena 分区限流fractal 示例的教学重点在于 fractal.hpp 中的fractal_group它同时持有两组并发的执行容器oneapi::tbb::task_group_context context[2]; oneapi::tbb::task_arena arenas[2]; oneapi::tbb::task_group groups[2];在 fractal.cpp 的run()中两个 arena 被初始化为不同的并发度arenas[0].initialize(num_threads); // 第一个分形完整线程数 arenas[1].initialize(num_threads / 2); // 第二个分形仅一半线程数这就是 README 所说不同并发级别的落点即使两块渲染区域大小相同、算法相同左侧与右侧分形也会因 arena 并发配额不同而呈现不同的计算吞吐。运行流程为第二个分形在arenas[1]中先启动groups[1].run(calc_fractal(1))第一个分形随后在arenas[0]中启动最后分别wait()汇合。每个 arena 内部又通过task_group承接分形计算任务实现了arena 限流 group 组织任务 context 管理取消三层结构。活动分形与取消机制fractal_group维护一个active标志fractal.hpp初始为 0第一个分形见 fractal.cpp。用户切换活动分形后switch_active会更新边框颜色以标识当前高优先级分形绿色为活动边框、灰绿色为非活动见 fractal.cpp。当用户通过键盘改变活动分形的参数移动、缩放、质量时fractal.hpp 中的每个操作方法在修改参数后会调用context[active].cancel_group_execution()取消该分形当前帧的计算从而让新参数立即生效下一帧渲染前fractal::run()会调用context.reset()复位上下文fractal.cpp。这个取消-复位循环是 oneTBB 任务取消语义的典型用法task_group_context允许以协作方式终止一组未完成的任务而无需粗暴地终止线程。像素计算与并行渲染原理单像素的 Mandelbrot 迭代calc_one_pixel 实现了标准的 Mandelbrot 逃逸时间算法将像素坐标映射到复平面fx0 (x - size_x/2)/magn cx对z z² c迭代直至模长平方超过 4 或达到max_iterations未逃逸的点iter max_iterations着白色其余点根据累加量mu映射为蓝绿渐变颜色。max_iterations同时受命令行参数与 GUI 热键控制quality_inc()/quality_dec()分别按50%/-50%调整迭代上限fractal.hpp。parallel_for blocked_range2d 的二维分块整幅分形通过 render 并行渲染把像素平面划分为blocked_range2dint(0, size_y, grain_size, 0, size_x, grain_size)的二维块每个块由fractal_body的operator()调render_rect逐像素计算。分块粒度即命令行参数grain-size默认 8。渲染的分块策略有两种默认使用simple_partitioner严格按 grain_size 划分块数固定传入use-auto-partitioner时改用auto_partitioner允许 oneTBB 依据负载动态调整分块减少不均衡开销。fractal::render中先拷贝分形对象再渲染fractal f *this;确保渲染期间对原对象的参数修改不会破坏正在执行的帧fractal.cpp 注释明确说明。每一帧由calc_fractal循环驱动while (v-next_frame() num_frames[num] ! 0)按帧数配额连续渲染并统计耗时fractal.cpp。GUI 交互热键当以图形界面编译并运行时示例支持以下热键摘自 README事件处理见 fractal_video.hpp键作用鼠标左键将所在分形设为活动分形w/s活动分形上移 / 下移a/d活动分形左移 / 右移q/e放大 / 缩小活动分形r/f提高 / 降低活动分形的质量每像素迭代次数esc停止执行其中q、e、r、f与方向键对应的底层实现均直接调用fractal_group的活动分形操作方法并触发上下文取消见 fractal_video.hpp 与 fractal.hpp。鼠标点击通过mouse_click判断点击点位于哪个分形区域内check_point并切换活动分形fractal.cpp任何交互后都会调用set_num_frames_at_least(20)保证至少再渲染 20 帧让操作效果可见fractal_video.hpp。小结与延伸阅读fractal 示例的价值在于以最小可运行体量覆盖了 oneTBB 的多项核心机制task_arena限制并发度、task_group组织任务、task_group_context协作取消、parallel_forblocked_range2d二维并行以及auto_partitioner与simple_partitioner的分块差异。动手验证时可先make light_test_fractal快速确认构建正确再make perf_run_fractal观察高迭代负载下的并行耗时最后以fractal auto 1 1000000 use-auto-partitioner silent对比两种分块策略的表现。如需进一步了解其他示例如何组合这些原语如图计算、并行流水线、并行归约等可阅读 examples/README.md 的样例总览而该示例所属的 task_arena 专题在 third-party/tbb/examples/task_arena 目录下与sub_string_finder等其他样例共同构成完整的 oneTBB 入门素材。【免费下载链接】moldmold: A Modern Linker 项目地址: https://gitcode.com/GitHub_Trending/mo/mold创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
