从 OpenMP 迁移至并发运行时

并发运行时支持各种编程模型。 这些模型可能会与其他库的模型重叠或对其进行补充。 本部分中的文档将 OpenMP 与并发运行时进行比较,并提供有关如何迁移现有 OpenMP 代码以使用并发运行时的示例。

OpenMP 编程模型由开放标准定义,具有与 Fortran 和 C/C++ 编程语言定义完善的绑定。 OpenMP 2.0 版和 2.5 版(由 Microsoft C++ 编译器支持)都很适合迭代的并行算法;也就是说,它们在数据数组上执行并行迭代。 OpenMP 3.0 除了迭代任务外,还支持非迭代任务。

当预设了并行度,并匹配了系统上的可用资源时,OpenMP 的效率最高。 OpenMP 模型特别适合将大量运算问题分配到单一计算机的处理资源中的高性能计算。 在此方案中,硬件环境通常是固定的,开发人员可以合理期望执行该算法时拥有对所有计算资源的独占访问权限。

但是,OpenMP 可能不适合约束较少的计算环境。 例如,通过使用 OpenMP 2.0 和 2.5 来实现递归问题(如快速排序算法或搜索数据树)会更加困难。 并发运行时通过提供异步代理库并行模式库 (PPL) 来补充 OpenMP 的功能。 异步代理库支持粗粒度任务并行性;PPL 支持更细粒度的并行任务。 并发运行时提供了并行执行操作所需的基础结构,以便可以专注于应用程序的逻辑。 但是,由于并发运行时支持各种编程模型,因此其计划开销可能大于其他并发库(如 OpenMP)。 因此,若要转换现有 OpenMP 代码以使用并发运行时,建议以增量方式测试性能。

适合从 OpenMP 迁移到并发运行时的情况

在以下情况下,迁移现有的 OpenMP 代码以使用并发运行时可能是有利的。

案例 并发运行时的优点
需要可扩展的并发编程框架。 并发运行时中的许多功能均可扩展。 还可以结合现有功能来构造新功能。 由于 OpenMP 依赖于编译器指令,不能轻松地对其进行扩展。
应用程序将受益于协作阻止。 当任务因需要尚不可用的资源而停滞时,并发运行时可以在第一个任务等待该资源时执行其他任务。
应用程序将受益于动态负载平衡。 并发运行时使用一种调度算法,该算法可随着工作负载的变化调整计算资源的分配。 在 OpenMP 中,当调度程序将计算资源分配给并行区域时,这些资源分配在整个计算过程中都是固定的。
需要异常处理支持。 使用 PPL 可以捕获并行区域或循环内外的异常。 在 OpenMP 中,必须处理并行区域或循环内的异常。
需要取消机制。 PPL 使应用程序能够取消单个任务和并行工作树。 OpenMP 要求应用程序实现其自己的取消机制。
需要并行代码才能在从其启动的不同上下文中完成。 并发运行时让你能在一个上下文中启动任务,然后在另一个上下文中等待或取消该任务。 在 OpenMP 中,所有并行工作都必须在开始的上下文中完成。
需要增强的调试支持。 Visual Studio 提供了“并行堆栈”和“并行任务”窗口,以便可以更轻松地调试多线程应用程序

有关调试并发运行时支持的详细信息,请参阅使用“任务”窗口使用并行堆栈窗口演练:调试并行应用程序

不适合从 OpenMP 迁移到并发运行时的情况

以下情况描述了何时可能不适合迁移现有 OpenMP 代码以使用并发运行时。

案例 说明
应用程序已经满足要求。 如果你对应用程序性能和当前调试支持感到满意,则迁移可能不合适。
并行循环正文执行很少的工作。 并发运行时任务计划程序的开销可能无法克服并行执行循环体的好处,尤其是在循环体相对较小时。
应用程序以 C 编写。 由于并发运行时使用许多 C++ 功能,因此当无法编写使 C 应用程序能够完全使用它的代码时,它可能不适合。

如何:转换 OpenMP 并行 for 循环以使用并发运行时

指定一个使用 OpenMP parallelfor 指令的基本循环,演示如何转换它以便使用并发运行时 concurrency::parallel_for 算法。

如何:转换使用取消的 OpenMP 循环以使用并发运行时
给定一个不需要运行所有迭代的 OpenMP parallelfor 循环,演示如何将其转换为使用并发运行时取消机制。

如何:转换使用异常处理的 OpenMP 循环以使用并发运行时
给定执行异常处理的 OpenMP parallelfor 循环,演示如何将其转换为使用并发运行时异常处理机制。

如何:转换使用缩减变量的 OpenMP 循环以使用并发运行时
给定一个使用 reduction 子句的 OpenMP parallelfor 循环,演示如何将其转换为使用并发运行时。

另请参阅

并发运行时
OpenMP
并行模式库 (PPL)
异步代理库