首页 > 其他分享 >原生并行版std::accumulate

原生并行版std::accumulate

时间:2023-12-03 20:46:06浏览次数:34  
标签:std 原生 unsigned long threads accumulate block

原生并行版std::accumulate

​ 代码来自《c++并发编程实战》

#include <iostream>
#include <numeric>
#include <algorithm>
#include <thread>
#include <functional>
#include <vector>
#include <chrono>
typedef long long LL;

template<typename Iterator, typename T>
struct accumulate_block{
    void operator()(Iterator first, Iterator last, T& result){
        result = std::accumulate(first, last, result);
    }
};

template<typename Iterator, typename T>
T parallel_accumulate(Iterator first, Iterator last, T init){
    unsigned long const length = std::distance(first, last);
    
    // 若输入范围为空 返回init的值
    if(!length)                 
        return init;

    // 确定启动的线程数
    unsigned long const min_per_thread = 25;
    unsigned long const max_threads = (length + min_per_thread - 1) / min_per_thread;

    // 能并发在一个程序的线程数量
    unsigned long const hardware_threads = std::thread::hardware_concurrency();
    // 确定最终的线程数量 若hardware_concurrency返回0则选择两个线程
    unsigned long const num_threads = std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
    // 每个线程中处理的元素数量
    unsigned long const block_size = length / num_threads;

    std::vector<T> results(num_threads);                // 存放中间结果
    std::vector<std::thread> threads(num_threads-1);    // 已有主线程 -1

    Iterator block_start = first;
    for(unsigned long i = 0; i < (num_threads - 1); i++){
        Iterator block_end = block_start;
        std::advance(block_end, block_size);            // block_end指向当前块的末尾
        // 启动一个新线程为当前块累加结果
        threads[i] = std::thread(accumulate_block<Iterator, T>(), block_start, block_end, std::ref(results[i]));
        block_start = block_end;                        // 当迭代器指向当前块末尾时启动一下一个块
    }
    // 处理最终块的结果
    accumulate_block<Iterator, T>()(block_start, last, results[num_threads - 1]);
    // 等待所有线程执行完毕
    std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
    // 返回最终结果
    return std::accumulate(results.begin(), results.end(), init);
}

int main(){
    std::vector<LL> v;
    LL sum = 0;
    for(LL i = 0;i <= 10000000; i++) v.push_back(i);
    
    auto beforeTime = std::chrono::steady_clock::now();

    //std::cout << parallel_accumulate(v.begin(), v.end(), sum) << std::endl;
    //std::cout << std::accumulate(v.begin(), v.end(), sum) << std::endl;

    auto afterTime = std::chrono::steady_clock::now();
    double duration_millsecond = std::chrono::duration<double, std::milli>(afterTime - beforeTime).count();
    std::cout << duration_millsecond << std::endl;
    return 0;
}

​ 0~10000000相加时测试如下。

image-20231203203812492

标签:std,原生,unsigned,long,threads,accumulate,block
From: https://www.cnblogs.com/zhangfirst1/p/17873696.html

相关文章

  • 马士兵鸿蒙原生开发工程师
    获取完整版--》请留言鸿蒙是华为推出的手机操作系统,之所以做这件事就是因为华为在世界通信领域具有扎实的技术功底,已经在某些领域抢了美国的风头,美国才倾全国之力去压制华为,并列出了针对华为的一系列措施,华为也确实感受到被卡了脖子。除此之外,随着物联网的呼声越来越大,各个电子产......
  • std::is_trivially_destructible的作用
    template<classTy>voiddestroy(Ty*pointer){destroy_one(pointer,std::is_trivially_destructible<Ty>{});}这样设计的好处主要体现在对泛型编程和内存管理的灵活性上。下面是一些可能的好处:1.**泛型性质:这种设计允许`destroy_one`在不同的上下文中使用,因为它是模......
  • 云原生技术分享 (二)
    三、Kubernetes  Kubernetes源于希腊语,意为“舵手”。k8s缩写是因为k和s之间有八个字符的原因。它是google在2015开源的容器调度编排的平台。它是建立在Google大规模运行生产工作负载(Borg系统)十几年经验的基础上,结合了社区中最优秀的想法和实践,已经成为了目前容器编排的事......
  • 【文档翻译】__cdecl/__stdcall/__fastcall?解开神秘的调用约定!
    本文档译自www.codeproject.com的文章"CallingConventionsDemystified",作者NemanjaTrifunovic,原文参见此处引言-Introduction在学习Windows编程的漫长、艰难而美妙的旅途中,你可能会对函数声明前出现的奇怪说明符感到好奇,比如__cdecl、__stdcall、__fastcall、WINAP......
  • 【PostgreSQL 数据库线下沙龙(武汉站)】PieCloudDB Database :云原生分布式虚拟数仓的诞
    2023年6月3日,开源软件联盟PostgreSQL中文社区在武汉举办了技术沙龙活动。本次活动主题围绕未来数据库展开讨论和分享。通过探讨未来数据库的概念和特点,为智能化时代的发展提供更多的支持和服务。同时,通过探讨数据库和AI技术的共生共荣,推动数字经济的发展和创新,开创未来数据库的新......
  • 【PostgreSQL 数据库技术峰会(成都站)】云原生虚拟数仓 PieCloudDB Database 的架构和关
    2023年6月17日,中国开源软件推进联盟PostgreSQL分会在成都举办了数据库技术峰会。此次峰会以“新机遇、新态势、新发展”为主题,结合当下信创热潮、人工智能等产业变革背景,探讨PostgreSQL数据库在这些新机遇下的发展前景。峰会邀请众多行业大咖、学术精英、技术专家、技术爱好者......
  • 一家国产云原生数据库的大胆设想
    作者黎燕微 伴随着云计算技术的深入应用,数据的处理与存储方式发生了天翻地覆的变化:数据库“上云”成为新潮,大量的数字化转型技术正在有效地利用云以改变我们业务开展的方式。 作者| 黎燕微 编辑 |龚晨霞 “科技无国界”或许只是一则童话故事。这两日,据外媒报道,美国政府又将......
  • 「拓数派(OpenPie)2022发布会实录 」PieCloudDB Database 新一代云原生存储引擎
    10月24日程序员节,拓数派「OpenPie」发布了云原生数据库PieCloudDBDatabase社区版与企业版。通过重新打造云上的数据库内核,突破了PC时代计算平台的限制,实现云上存算分离。PieCloudDB基于云的基础设施,专为云平台打造。本文整理自拓数派「OpenPie」2022发布会的演讲,将为大家着重介......
  • 「拓数派(OpenPie)2022发布会实录 」PieCloudDB Database智能化云原生平台
    作为一款云原生eMPP数据库,PieCloudDBDatabase的部署和管控也是云原生的。PieCloudDB为用户提供了智能化云原生平台,提供数据洞察、元数据浏览、用户管理、权限管理、SQL执行、ETL管理等功能,可视化管理平台界面使用户得以更方便地在网页端进行管理。本文整理自拓数派「OpenPie」202......
  • 【DTCC 2022】云原生数据库PieCloudDB全新eMPP架构是如何炼成的
    12月14-16日,第十三届中国数据库技术大会(DTCC2022)在线上隆重召开。拓数派赞助并参与了数据库盛会DTCC,在会议中,拓数派CTO郭罡分享了《云原生数据库PieCloudDB eMPP架构设计与实现》的主题演讲。在演讲中,郭罡分析了传统分布式MPP架构的痛点,介绍了云原生数据库PieCloudDB的eMPP架......