C++并发编程——在运行时选择线程数量

本文介绍了一种基于C++标准库实现的多线程并行计算方法,通过将任务分割成若干子任务并行处理来加速累加操作的计算过程。文章详细解释了如何根据硬件特性确定最优线程数,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在编写多线程程序时,运行多少线程比较合适呢?线程并不是越多越好,理论上,硬件支持多少线程数,就开多少个线程比较合适,有的比如完成端口IOCP中建议开2倍线程数,因为考虑到有些线程可能会挂起等情况。但最重要的一条,首先要获取当前硬件支持的线程数,通常情况下为CPU核数。

std::thread::hardware_concurrency();    //获取当前CPU核心数量

代码示例:
以下代码为std::accumulate的简单并行版本实现,通过将大量的累加操作,分配给多个线程去计算,最后将各个线程计算的结果累加,得出最终结果。真正的并行计算任务分割是很麻烦的,这里并不需要考虑线程的同步等问题。

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);
    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();   //获取当前CPU核心数量
    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);

    Iterator block_start=first;
    std::vector<std::thread> v_threads(num_threads-1);
    for(unsigned long i=0;i<num_threads-1;++i)
    {
        Iterator block_end=block_start;
        std::advance(block_end,block_size);
        v_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(v_threads.begin(),v_threads.end(),std::mem_fn(&std::thread::join));//等待所有线程计算完成

    return std::accumulate(results.begin(),results.end(),init);
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<int> v(100000);
    std::iota(v.begin(),v.end(),1);
    long long sum=parallel_accumulate(v.begin(),v.end(),0);
    cout<<"sum="<<sum<<endl;
    return 0;
}

相关STL源码:

//std::distance源码
template<class _BidIt,
    class _Diff> inline
        void _Distance2(_BidIt _First, _BidIt _Last, _Diff& _Off,
            bidirectional_iterator_tag)
    {   // add to _Off distance between bidirectional iterators (redundant)
    for (; _First != _Last; ++_First)
        ++_Off;
    }

template<class _InIt> inline
    typename iterator_traits<_InIt>::difference_type
        distance(_InIt _First, _InIt _Last)
    {   // return distance between iterators
    typename iterator_traits<_InIt>::difference_type _Off = 0;
    _Distance2(_First, _Last, _Off, _Iter_cat(_First));
    return (_Off);
    }
//std::advance源代码
    // TEMPLATE FUNCTION advance
template<class _InIt,
    class _Diff> inline
    void _Advance(_InIt& _Where, _Diff _Off, input_iterator_tag)
    {   // increment iterator by offset, input iterators
 #if _ITERATOR_DEBUG_LEVEL == 2
    if (_Off < 0)
        _DEBUG_ERROR("negative offset in advance");
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    for (; 0 < _Off; --_Off)
        ++_Where;
    }

template<class _FwdIt,
    class _Diff> inline
    void _Advance(_FwdIt& _Where, _Diff _Off, forward_iterator_tag)
    {   // increment iterator by offset, forward iterators
 #if _ITERATOR_DEBUG_LEVEL == 2
    if (_Off < 0)
        _DEBUG_ERROR("negative offset in advance");
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    for (; 0 < _Off; --_Off)
        ++_Where;
    }

template<class _BidIt,
    class _Diff> inline
    void _Advance(_BidIt& _Where, _Diff _Off, bidirectional_iterator_tag)
    {   // increment iterator by offset, bidirectional iterators
    for (; 0 < _Off; --_Off)
        ++_Where;
    for (; _Off < 0; ++_Off)
        --_Where;
    }

template<class _RanIt,
    class _Diff> inline
    void _Advance(_RanIt& _Where, _Diff _Off, random_access_iterator_tag)
    {   // increment iterator by offset, random-access iterators
    _Where += _Off;
    }

template<class _InIt,
    class _Diff> inline
    void advance(_InIt& _Where, _Diff _Off)
    {   // increment iterator by offset, arbitrary iterators
    _Advance(_Where, _Off, _Iter_cat(_Where));
    }
//获取硬件线程数量
    static unsigned int hardware_concurrency() _NOEXCEPT
        {   // return number of hardware thread contexts
        return (::Concurrency::details::_GetConcurrency());
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值