方法: マップ操作と縮小操作を並列実行する

次の使用例を使用する方法を示しています、 concurrency::parallel_transform と concurrency::parallel_reduce アルゴリズムと、 concurrency::concurrent_unordered_map クラスは、ファイル内の単語の出現をカウントします。

A 地図操作シーケンス内の各値には関数を適用します。A 削減操作に 1 つの値のシーケンスの要素を結合します。標準テンプレート ライブラリ (STL) を使用することができます std::transformstd::accumulate マップを実行し、操作を削減するためのクラス。ただし、多くの問題のパフォーマンスを向上させるには、使用できます、 parallel_transformマップ操作を並行して実行するのには、アルゴリズムと、 parallel_reduceアルゴリズムは並列で下げる操作を実行します。場合によっては、使用できますconcurrent_unordered_map 1 回の操作で、マップし、削減を実行します。

使用例

次の使用例は、ファイル内の単語の出現をカウントします。それを使用して std::vector 2 つのファイルの内容を表します。Map の操作は、各ベクトル内の各単語の出現を計算します。縮小操作両方のベクトルに単語数を蓄積します。

// parallel-map-reduce.cpp
// compile with: /EHsc
#include <ppl.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <unordered_map>
#include <windows.h>

using namespace concurrency;
using namespace std;

class MapFunc 
{ 
public:
    unordered_map<wstring, size_t> operator()(vector<wstring>& elements) const 
    { 
        unordered_map<wstring, size_t> m;
        for_each(begin(elements), end(elements), [&m](const wstring& elem)
        { 
            m[elem]++;
        });
        return m; 
    }
}; 

struct ReduceFunc : binary_function<unordered_map<wstring, size_t>, 
                    unordered_map<wstring, size_t>, unordered_map<wstring, size_t>>
{
    unordered_map<wstring, size_t> operator() (
        const unordered_map<wstring, size_t>& x, 
        const unordered_map<wstring, size_t>& y) const
    {
        unordered_map<wstring, size_t> ret(x);
        for_each(begin(y), end(y), [&ret](const pair<wstring, size_t>& pr) {
            auto key = pr.first;
            auto val = pr.second;
            ret[key] += val;
        });
        return ret; 
    }
}; 

int wmain()
{ 
    // File 1 
    vector<wstring> v1;
    v1.push_back(L"word1"); //1 
    v1.push_back(L"word1"); //2 
    v1.push_back(L"word2"); 
    v1.push_back(L"word3"); 
    v1.push_back(L"word4"); 

    // File 2 
    vector<wstring> v2; 
    v2.push_back(L"word5"); 
    v2.push_back(L"word6"); 
    v2.push_back(L"word7"); 
    v2.push_back(L"word8"); 
    v2.push_back(L"word1"); //3 

    vector<vector<wstring>> v;
    v.push_back(v1);
    v.push_back(v2);

    vector<unordered_map<wstring, size_t>> map(v.size()); 

    // The Map operation
    parallel_transform(begin(v), end(v), begin(map), MapFunc()); 

    // The Reduce operation 
    unordered_map<wstring, size_t> result = parallel_reduce(
        begin(map), end(map), unordered_map<wstring, size_t>(), ReduceFunc());

    wcout << L"\"word1\" occurs " << result.at(L"word1") << L" times. " << endl;
} 
/* Output:
   "word1" occurs 3 times.
*/

コードのコンパイル

コードをコンパイルするには、コピーし、Visual Studio プロジェクト内に貼り付けるまたはという名前のファイルに貼り付けて並列・ マップ-reduce.cpp と、Visual Studio のコマンド プロンプト ウィンドウで次のコマンドを実行します。

cl.exe /EHsc parallel-map-reduce.cpp

信頼性の高いプログラミング

この例では、使用できます、 concurrent_unordered_mapクラス: concurrent_unordered_map.h—to で定義されているマップを実行し、1 回の操作での削減します。

// File 1 
vector<wstring> v1;
v1.push_back(L"word1"); //1 
v1.push_back(L"word1"); //2 
v1.push_back(L"word2"); 
v1.push_back(L"word3"); 
v1.push_back(L"word4"); 

// File 2 
vector<wstring> v2; 
v2.push_back(L"word5"); 
v2.push_back(L"word6"); 
v2.push_back(L"word7"); 
v2.push_back(L"word8"); 
v2.push_back(L"word1"); //3 

vector<vector<wstring>> v;
v.push_back(v1);
v.push_back(v2);

concurrent_unordered_map<wstring, size_t> result;
for_each(begin(v), end(v), [&result](const vector<wstring>& words) {
    parallel_for_each(begin(words), end(words), [&result](const wstring& word) {
        InterlockedIncrement(&result[word]);
    });
});

wcout << L"\"word1\" occurs " << result.at(L"word1") << L" times. " << endl;

/* Output:
   "word1" occurs 3 times.
*/

通常、のみ、外部または内部のループ並列化します。相対的にいくつかのファイルがあるし、各ファイルには多くの単語が含まれている場合、内側のループを並列化します。比較的多数のファイルがあるし、各ファイルにはいくつかの単語が含まれている場合、外側のループを並列化します。

参照

関連項目

parallel_transform 関数

parallel_reduce 関数

concurrent_unordered_map クラス

概念

並列アルゴリズム