2.4実行時のスレッド数の決定

2208 ワード

std::thread::hardware_concurrency()C++標準ライブラリでは、この関数は、1つのプログラムに同時に実行できるスレッドの数を返します.
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<:thread> 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はクラスのメンバー関数を適合させるために使用される.メンバー関数を関数オブジェクトに変換し、オブジェクトポインタまたはオブジェクト(参照)を使用してバインドします.