异步调用std::async实现并行计算

256 篇文章 3 订阅
149 篇文章 2 订阅

一 std::async

template< class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
    async( Function&& f, Args&&... args );

std::async返回一个future对象,可通过get方法异步获取执行结果,如下所示:

#include <iostream>
#include <string>
#include <future>
 
std::string helloFunction(const std::string& s) {
    return "Hello C++11 from " + s + ".";
}
 
class HelloFunctionObject {
public:
    std::string operator()(const std::string& s) const {
        return "Hello C++11 from " + s + ".";
    }
};
 
int main() {
    // 带函数的future
    auto futureFunction = std::async(helloFunction, "function");
    // 带函数对象的future
    HelloFunctionObject helloFunctionObject;
    auto futureFunctionObject = std::async(helloFunctionObject, "function object");
    // 带匿名函数的future
    auto futureLambda = std::async([](const std::string& s) {return "Hello C++11 from " + s + "."; }, "lambda function");
    std::cout << futureFunction.get() << std::endl;
    std::cout << futureFunctionObject.get() << std::endl;
    std::cout << futureLambda.get() << std::endl;
}

二 std::async实现并行计算

1.主程序:

#include <iostream>
#include <vector>
#include <future>
#include <random>
#include <numeric>
#include <cassert>
#include "time_elapse.hpp"
static const int NUM = 100000000;
long long parallel_inner_product(std::vector<int>&v, std::vector<int>&w) {
    if (v.size() != w.size()) {
        return 0;
    }
    if (v.size() < 100) {
        return std::inner_product(begin(v), end(v), begin(w), 0LL);
    }
 
    auto future1 = std::async([&] { return std::inner_product(&v[0], &v[v.size() / 4], &w[0], 0LL); });
    auto future2 = std::async([&] { return std::inner_product(&v[v.size() / 4], &v[v.size() / 2], &w[v.size() / 4], 0LL); });
    auto future3 = std::async([&] { return std::inner_product(&v[v.size() / 2], &v[v.size() * 3 / 4], &w[v.size() / 2], 0LL); });
    auto future4 = std::async([&] { return std::inner_product(&v[v.size() * 3 / 4], &v[v.size()], &w[v.size() * 3 / 4], 0LL); });
 
    return future1.get() + future2.get() + future3.get() + future4.get();
}
long long serial_inner_product(std::vector<int>&v, std::vector<int>&w) {
    if (v.size() != w.size()) {
        return 0;
    }
    return std::inner_product(begin(v), end(v), begin(w), 0LL);
}
int main() {
    std::random_device seed;
    std::mt19937 engine(seed());
    std::uniform_int_distribution<int> dist(0, 100);
    std::vector<int> v, w;
    v.reserve(NUM);
    w.reserve(NUM);
    time_elapse te;
    te.start();
    for (int i = 0; i < NUM; ++i) {
        v.push_back(dist(engine));
        w.push_back(dist(engine));
    }
    std::cout << "load vector elapse = " << te.end() << "s" << std::endl;
    te.start();
    auto res1 = parallel_inner_product(v, w);
    std::cout << "parallel inner_product elapse = " << te.end() << "s" << std::endl;
 
    te.start();
    auto res2 = serial_inner_product(v, w);
    std::cout << "serial inner_product elapse = " << te.end() << "s" << std::endl;
  
    assert(res1 == res2);
 
    return 0;
}

2.time_elapse.hpp

#include <chrono>
struct time_elapse {
    void start() {
        start_ = std::chrono::steady_clock::now();
    }
    double end() {
        std::chrono::duration<double>dura = std::chrono::steady_clock::now() - start_;
        return dura.count();
    }
private:
    std::chrono::time_point<std::chrono::steady_clock> start_ = std::chrono::steady_clock::now();
};

3.编译脚本make.sh

g++ -std=c++11 -g -o Test test.cpp -pthread

三 程序性能测试

1.测试环境:

(1)国产环境(实体机)

CPU:

OS:

(2)Intel环境(虚拟机)

CPU:

 OS:

2.测试结果对比:

(1)国产环境测试结果(执行两次)

 

(2)Interl环境测试结果(执行两次)

 

3.测试结论

(1)使用std::async优化后的并行计算比串行更节省时间;

(2)国产化环境并没有太多优势,反而调用C++相关库更慢。

https://github.com/wangzhicheng2013/async_parallel

 

std::async是C++11标准库中的一个函数模板,用于创建一个异步任务,返回一个std::future对象,可以通过std::future对象获取异步任务的结果。 std::async的用法有以下几个步骤: 1. 包含头文件#include<future>。 2. 使用std::async创建异步任务,传入一个可调用对象(函数、函数指针、lambda表达式等)作为参数,标识异步任务的启动。 3. std::async会返回一个std::future对象,可以通过该对象获取异步任务的结果。 4. 可以通过std::future的成员函数get()获取异步任务的返回值,该调用会阻塞当前线程,直到异步任务完成并返回结果。也可以通过std::future的成员函数wait()等待异步任务的完成,再通过get()获取结果。 5. 可以通过std::future的成员函数valid()检查std::future对象是否可用,即异步任务是否完成并返回结果。 6. std::async还可以传入std::launch参数,显式指定异步任务的启动策略。例如,std::launch::async表示立即启动异步任务;std::launch::deferred表示延迟启动异步任务,直到调用std::future的成员函数get()或wait()时才启动。 7. 当std::async创建的异步任务完成后,std::future对象将被销毁,对std::future对象的后续操作将导致未定义的行为。 总而言之,std::async可以用于创建一个异步任务,并获得任务的返回值。它提供了一种简单的方式来进行并行编程,可以提高程序的性能和响应能力。但是需要注意的是,需要合理使用std::future对象以及与其相关的成员函数来处理异步任务的结果,避免潜在的阻塞或无效操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值