当前位置: 首页 > news >正文

windows C++-有效使用PPL(四)

当取消并行工作时,不要执行阻止操作

如果可能,在调用 concurrency::task_group::cancel 或 concurrency::structured_task_group::cancel 方法取消并行工作之前不要执行阻止操作。

在任务执行协作停滞操作时,运行时可在第一个任务等待数据时执行其他工作。 当运行时取消停滞时,它将重新安排正在等待的任务。 通常运行时会先重新安排最近取消停滞的任务,然后再重新安排后来取消停滞的任务。 因此,运行时在停滞操作期间可能安排不必要的工作,这会导致性能下降。 相应地,如果在取消并行工作前执行停滞操作,则停滞操作会延迟对 cancel 的调用。 这将导致其他任务执行不必要的工作。

请看下面定义 parallel_find_answer 函数的示例,该函数搜索所提供的满足提供的谓词函数的数组的元素。 当谓词函数返回 true 时,并行工作函数会创建一个 Answer 对象并取消整个任务。

// blocking-cancel.cpp
// compile with: /c /EHsc
#include <windows.h>
#include <ppl.h>using namespace concurrency;// Encapsulates the result of a search operation.
template<typename T>
class Answer
{
public:explicit Answer(const T& data): _data(data){}T get_data() const{return _data;}// TODO: Add other methods as needed.private:T _data;// TODO: Add other data members as needed.
};// Searches for an element of the provided array that satisfies the provided
// predicate function.
template<typename T, class Predicate>
Answer<T>* parallel_find_answer(const T a[], size_t count, const Predicate& pred)
{// The result of the search.Answer<T>* answer = nullptr;// Ensures that only one task produces an answer.volatile long first_result = 0;// Use parallel_for and a task group to search for the element.structured_task_group tasks;tasks.run_and_wait([&]{// Declare the type alias for use in the inner lambda function.typedef T T;parallel_for<size_t>(0, count, [&](const T& n) {if (pred(a[n]) && InterlockedExchange(&first_result, 1) == 0){// Create an object that holds the answer.answer = new Answer<T>(a[n]);// Cancel the overall task.tasks.cancel();}});});return answer;
}

new 运算符可执行可能会停滞的堆分配。 仅当任务执行协作阻止调用(例如对 concurrency::critical_section::lock 的调用)时,运行时才会执行其他工作。

下面的示例介绍如何防止不必要的工作,从而提高性能。 此示例在为 Answer 对象分配存储前先取消任务组。

// Searches for an element of the provided array that satisfies the provided
// predicate function.
template<typename T, class Predicate>
Answer<T>* parallel_find_answer(const T a[], size_t count, const Predicate& pred)
{// The result of the search.Answer<T>* answer = nullptr;// Ensures that only one task produces an answer.volatile long first_result = 0;// Use parallel_for and a task group to search for the element.structured_task_group tasks;tasks.run_and_wait([&]{// Declare the type alias for use in the inner lambda function.typedef T T;parallel_for<size_t>(0, count, [&](const T& n) {if (pred(a[n]) && InterlockedExchange(&first_result, 1) == 0){// Cancel the overall task.tasks.cancel();// Create an object that holds the answer.answer = new Answer<T>(a[n]);            }});});return answer;
}
不要在并行循环中写入共享数据

并发运行时提供了多种数据结构,例如 concurrency::critical_section,它们可以同步对共享数据的并发访问。 很多情况下这些数据结构非常有用,例如,当多个任务很少需要对资源的共享访问时。

请考虑以下示例,该示例使用 concurrency::parallel_for_each 算法和 critical_section 对象来计算 std::array 对象中的素数计数。 此示例不会进行扩展,因为每个线程必须等待以访问共享的变量 prime_sum。

critical_section cs;
prime_sum = 0;
parallel_for_each(begin(a), end(a), [&](int i) {cs.lock();prime_sum += (is_prime(i) ? i : 0);cs.unlock();
});

此示例也可能导致性能不佳,因为频繁的锁定操作有力地对循环进行了序列化。 此外,当并发运行时对象执行停滞操作时,计划程序可能会在第一个线程等待数据时创建其他线程来执行其他工作。 如果运行时因许多任务正等待共享数据而创建许多线程,那么应用程序可能不会很好地运行,或进入资源不足的状态。

PPL 定义了 concurrency::combinable 类,它通过以无锁方式提供对共享资源的访问来帮助消除共享状态。 combinable 类提供了线程本地存储,该存储允许你执行细化的计算,然后将这些计算合并为最终的结果。 你可以将 combinable 对象当作 reduction 变量。

下面的示例使用 combinable 对象而不是 critical_section 对象来计算总和,从而修改前一个结果。 此示例可进行缩放,因为每个线程都会保存自己的总和本地副本。 此示例使用 concurrency::combinable::combine 方法将本地计算合并为最终结果。

combinable<int> sum;
parallel_for_each(begin(a), end(a), [&](int i) {sum.local() += (is_prime(i) ? i : 0);
});
prime_sum = sum.combine(plus<int>());

http://www.mrgr.cn/news/53519.html

相关文章:

  • Golang | Leetcode Golang题解之第492题构造矩形
  • 华为OD机试2024年真题( 最远足迹)
  • Python库matplotlib之十一
  • manimgl 安装win7
  • Vue脚手架学习 vue脚手架配置代理、插槽、Vuex使用、路由、ElementUi插件库的使用
  • 判断推理学习
  • snmpbulkwalk使用说明
  • CVTE Android面试题及参考答案
  • 查缺补漏----三次握手与四次挥手
  • 用友 NCC SPR 日志工具的使用
  • git区分大小写吗?如果不区分,那要如何设置?
  • SQLI LABS | Less-1 GET - Error based - Single Quotes - String
  • HCIA复习实验
  • 查缺补漏----Cache命中率与缺失率的辨析
  • Guava防击穿回源
  • 蚂蚁华东师范大学:从零开始学习定义和解决一般优化问题LLMOPT
  • 动态规划一>下降路径最小和
  • 代码随想录算法训练营第48天| 739. 每日温度,496.下一个更大元素 I,503.下一个更大元素II
  • 华为OD机试2024年真题(基站维修工程师)
  • 网页打印——魔都千丝冥缘——未来之窗行业应用跨平台架构