C++标准库中的算法与应用之一

非修改序列

for_each

  1. 按顺序将给定的函数对象f应用于解引用范围为[first,last)的每个迭代器的结果。
  2. 将给定的函数对象f应用于解引用[first,last)范围内的每个迭代器的结果(不一定按顺序)。
  3. 根据策略执行

对于这两个重载,如果迭代器类型是可变的,则f可以通过取消引用的迭代器来修改范围的元素。如果f返回结果,则忽略该结果。

与其余并行算法不同,for_each不允许复制序列中的元素,即使它们是可复制的。

#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

int main()
{
   
    vector<int> nums{
   31, 14, 20, 28, 35, 27};
    int sum = 0;
	
    auto print = [](const int& n) {
    std::cout << " " << n; };
 
    cout << "before:";
    for_each(nums.cbegin(), nums.cend(), print);
    cout << endl;
 
    for_each(nums.begin(), nums.end(), [](int &n){
    n++; });
 
    for_each(nums.begin(), nums.end(), [=, &sum](int n){
   sum += n;});
 
    cout << "after: ";
    for_each(nums.cbegin(), nums.cend(), print);
    cout << '\n';
    cout << "sum: " << sum << '\n';
}

输出结果

before: 31 14 20 28 35 27
after:  32 15 21 29 36 28
sum: 161

执行策略ExecutionPolicy

如果执行策略类型用作唯一类型,则可以消除并行算法重载的歧义

  1. 如果要求不得并行执行并行算法。通常指定执行策略为std :: execution :: seq,用此策略调用的并行算法中,访问元素的函数调用,在调用线程中无法确定其顺序。
  2. 如果要求并行算法的执行可以并行化。通常指定执行策略为std :: execution :: par,使用此策略调用的并行算法中,访问的元素函数调用,可以在调用线程中执行,也可以在库隐式创建的线程中执行,以支持并行算法执行。在同一线程中执行的任何此类调用,它们的相对次序不能确定。
  3. 指示并行算法的执行可以在线程之间并行化,向量化或迁移。使用此策略调用的并行算法中的元素访问函数的调用,可以在未指定的线程中以无序方式执行,并且在每个线程中彼此之间没有顺序。
  4. 指示可以对并行算法的执行进行矢量化处理,例如,使用对多个数据项进行操作的指令在单个线程上执行。
    在使用这些执行策略中的任何一个,执行并行算法的过程中,如果元素访问函数的调用,通过未捕获的异常退出,则将调用std :: terminate。

parallel_policy策略

使用执行策略

#include <vector>
#include <algorithm>
#include <iostream>
#include <mutex>
#include <execution>

using namespace std;

int main()
{
   
    vector<int> nums{
   31, 14, 20, 28, 35, 27};
	mutex m;
	int   sum=0;
	
    auto print = [](const int& n) {
    std::cout << " " << n; };
 
    cout << "before:";
    for_each(nums.cbegin(), nums.cend(), print);
    cout << endl;
 
	for_each(execution::par, nums.cbegin(), nums.cend(), 
				[&](int n) {
   
					lock_guard<mutex> guard(m);
					sum += n; 
				});
 
    cout << "after: ";
    for_each(nums.cbegin(), nums.cend(), print);
    cout << '\n';
    cout << "sum: " << sum << '\n';
}

输出结果

before: 31 14 20 28 35 27
after:  31 14 20 28 35 27
sum: 155

上述使用了并行执行策略,所以,使用mutex避免数据争用。

sequenced_policy策略

此策略不是并行执行策略:使用它会强制实现,在调用该函数的线程上执行所有操作,因此不存在并行性。但是它仍然是一个执行策略,因此对算法复杂性和异常影响的影响与其他标准策略相同。
不仅所有操作都必须在同一线程上执行,而且必须以一定的顺序执行,因此它们不会交错。确切的顺序是不确定的,并且在函数的不同调用之间可能会有所不同。特别是,如果没有执行策略,则不能保证操作的执行顺序与相应重载的执行顺序相同。例如,对std :: for_each的以下调用将以未指定的顺序填充数字1-1,000的向量。这与没有执行策略的重载形成对比,后者将按顺序存储数字:

count/count_if

返回满足特定条件,在[first,last)范围内的元素的数目。

  1. 计算等于某个值的元素。
  2. 计算谓词p返回true的元素。
  3. 根据策略执行。
#include <algorithm>
#include <iostream>
#include <array>
#include <execution>

using namespace std;

int main()
{
   
    constexpr array<int,10> v = {
    1, 2, 3, 4, 4, 3, 7, 8, 9, 10 };
 
    int target1 = 3;
    int target2 = 5;
	
    int num_items1 = count(v.begin(), v.end(), target1);
    int num_items2 = count(v.begin(), v.end(), target2);
	
    cout << "number: " << target1 << " count: " << num_items1 << '\n';
    cout << "number: " << target2 << " count: " << num_items2 << '\n';
 
    int num_items3 = count_if(v.begin(), v.end(), [](int i){
   return i % 3 == 0;});
    cout << "number divisible by three: " << num_items3 << '\n';
 
    auto distance = [](auto first, auto last) {
   
        return count_if(first, last, [](auto n){
   if (n>5) return true; else return false;});
    };
    cout << "distance: " << distance(v.begin(), v.end()) << endl;

	auto num_items4 = count_if(execution::par, v.begin(), v.end
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值