2.4在运行时决定线程数量

std::thread::hardware_concurrency()在C++标准库中,这个函数将返回能同时并发在一个程序中的线程数量。

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

};

template
T Parallel_accumulate(Iterator first, Iterator last, T init)
{
    //输入范围,length
    unsigned long long length = std::distance(first, last);
    if (!length)     //1
        return init;

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

    unsigned long const hardware_threads =
        std::thread::hardware_concurrency();

    //启动线程数量的确定
    unsigned long const num_threads = //3
        std::min(hardware_threads != 0 ? hardware_threads : max_threads);
    //每个线程中的元素数量
    unsigned long const block_size = length / num_threads; //4
    std::vector results(num_threads);
    //启动的线程数必须必num_threads少1个,因为在启动之前已经有一个主线程了。
    std::vector threads(num_threads - 1);//5

    Iterator block_start = first;
    for (unsigned long i = 0; i < (num_threads - 1); ++i)
    {
        Iterator block_end = block_start;
        //block_end指向当前块的末尾
        std::advance(block_end, block_size);//6

        //启动一个新线程为当前块累加结果
        threads[i] = std::thread( //7
            accumulate_block(),
            block_start, block_end, std::ref(results[i]));
        //当迭代器指向当前块的末尾时,启动下一块
        block_start = block_end; //8
    }
    //处理最终块的结果
    accumulate_block()(
        block_start, last, results[num_threads - 1]); //9
    std::for_each(threads.begin(), threads.end(),
        std::mem_fn(&std::thread::join)); //10
    return std::accumulate(results.begin(), results.end(), init); //11
}

启动线程数量的确定,计算量的最大值和硬件支持线程数中较小的值为启动线程数量。

mem_fn
mem_fn里面的mem就是指类的成员member, 而fn就是指function, 加在一起就是说member function,即mem_fn是用来适配类的成员函数的。把成员函数转为函数对象,使用对象指针或对象(引用)进行绑定。

你可能感兴趣的:(2.4在运行时决定线程数量)