ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 并行计算大矢量的总和

2019-08-30 07:18:17  阅读:223  来源: 互联网

标签:c multithreading algorithm parallel-processing boost-asio


问题背景

我有一个程序目前花了太长时间总结使用std :: accumulate的大约1亿个元素的大型std ::向量,这是一个瓶颈.

我希望它更快,我希望它是一个异步计算,所以GUI / Server不会阻止.计算也应该使用多线程,这样我就可以减少总结向量所需的时间.

我想分割求和,以便每个线程对向量的一部分求和,然后当计算所有部分和时,应将每个线程的部分和加在一起以得到总和.

Boost.Asio的?

我想知道如何在Boost.Asio中解决这个问题?理想情况下,我的程序需要重用线程(如线程组),不确定如何存储和检索部分和,最后检索部分和的总和.

我正在考虑创建一个调用boost :: asio :: io_service :: run的线程组,传递一个处理程序来计算部分和,但我不知道如何将部分和传递给另一个处理程序并添加所有部分总结在一起.

如果有人展示了我可以解决这个问题的一些骷髅代码,那就太棒了.

解决方法:

Boost.Asio适合这个问题吗?

Boost.Asio的主要目的是为网络和I / O编程提供异步模型,您描述的问题似乎与网络和I / O无关.

我认为最简单的解决方案是使用Boost或C标准库提供的线程原语.

并行算法

这是仅使用标准库创建的并行版本累积的示例.

/* Minimum number of elements for multithreaded algorithm.
   Less than this and the algorithm is executed on single thread. */
static const int MT_MIN_SIZE = 10000;

template <typename InputIt, typename T>
auto parallel_accumulate(InputIt first, InputIt last, T init) {
    // Determine total size.
    const auto size = std::distance(first, last);
    // Determine how many parts the work shall be split into.
    const auto parts = (size < MT_MIN_SIZE)? 1 : std::thread::hardware_concurrency();

    std::vector<std::future<T>> futures;

    // For each part, calculate size and run accumulate on a separate thread.
    for (std::size_t i = 0; i != parts; ++i) {
        const auto part_size = (size * i + size) / parts - (size * i) / parts;
        futures.emplace_back(std::async(std::launch::async,
            [=] { return std::accumulate(first, std::next(first, part_size), T{}); }));
        std::advance(first, part_size);
    }

    // Wait for all threads to finish execution and accumulate results.
    return std::accumulate(std::begin(futures), std::end(futures), init,
        [] (const T prev, auto& future) { return prev + future.get(); });
}

Live example(并行版本与Coliru上的顺序执行大致相同,可能只有1个核心可用)

计时

在我的机器上(使用8个线程),并行版本平均提供了约120%的性能提升.

Sequential sum:
Time taken: 46 ms
5000000050000000
——————————–
Parallel sum:
Time taken: 21 ms
5000000050000000

但是,100,000,000个元素的绝对增益只是微不足道的(25毫秒).虽然,在累积不同于int的元素类型时,性能增益可能会更大.

OpenMP的

正如@sehe在评论中所提到的,值得一提的是OpenMP可能会为这个问题提供一个简单的解决方案,例如:

template <typename T, typename U>
auto omp_accumulate(const std::vector<T>& v, U init) {
    U sum = init;

    #pragma omp parallel for reduction(+:sum)
    for(std::size_t i = 0; i < v.size(); i++) {
        sum += v[i];
    }

    return sum;
}

在我的机器上,此方法与使用标准线程基元的并行方法执行相同的操作.

Sequential sum:
Time taken: 46 ms
5000000050000000
——————————–
Parallel sum:
Time taken: 21 ms
Sum: 5000000050000000
——————————–
OpenMP sum:
Time taken: 21 ms
Sum: 5000000050000000

标签:c,multithreading,algorithm,parallel-processing,boost-asio
来源: https://codeday.me/bug/20190830/1766212.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有