当前位置: 首页 > news >正文

windows C++-并行编程-使用 parallel_invoke 来执行并行操作

此示例演示如何使用 concurrency::parallel_invoke 算法提高对共享数据源执行多项操作的程序的性能。 因为没有操作会修改源,所以可以直接的方式并行执行。

示例:在变量上创建、初始化和执行操作

请考虑以下代码示例,该示例创建一个 MyDataType 类型的变量,调用函数来初始化该变量,然后对该数据执行多个长时操作。

MyDataType data;
initialize_data(data);lengthy_operation1(data);
lengthy_operation2(data);
lengthy_operation3(data);

如果 lengthy_operation1、lengthy_operation2 和 lengthy_operation3 函数不修改 MyDataType 变量,则可以并行执行这些函数,而无需进行其他修改。

示例:并行运行上一个示例

以下示例修改上一个示例以并行运行。 parallel_invoke 算法并行执行每个任务,并在完成所有任务后返回。

MyDataType data;
initialize_data(data);concurrency::parallel_invoke([&data] { lengthy_operation1(data); },[&data] { lengthy_operation2(data); },[&data] { lengthy_operation3(data); }
);
示例:对下载的文件执行多个操作

以下示例从 gutenberg.org 下载 Homer 的 The Iliad,并对该文件执行多个操作。 该示例首先串行执行这些操作,然后并行执行相同的操作。

// parallel-word-mining.cpp
// compile with: /EHsc /MD /DUNICODE /D_AFXDLL
#define _WIN32_WINNT 0x0501
#include <afxinet.h>
#include <ppl.h>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>using namespace concurrency;
using namespace std;// Calls the provided work function and returns the number of milliseconds 
// that it takes to call that function.
template <class Function>
__int64 time_call(Function&& f)
{__int64 begin = GetTickCount();f();return GetTickCount() - begin;
}// Downloads the file at the given URL.
CString get_http_file(CInternetSession& session, const CString& url);// Adds each word in the provided string to the provided vector of strings.
void make_word_list(const wstring& text, vector<wstring>& words);// Finds the most common words whose length are greater than or equal to the 
// provided minimum. 
vector<pair<wstring, size_t>> find_common_words(const vector<wstring>& words, size_t min_length, size_t count);// Finds the longest sequence of words that have the same first letter.
vector<wstring> find_longest_sequence(const vector<wstring>& words);// Finds all pairs of palindromes that appear in the provided collection
// of words.
vector<pair<wstring, wstring>> find_palindromes(const vector<wstring>& words,size_t min_length);int wmain()
{  // Manages the network connection.CInternetSession session(L"Microsoft Internet Browser");// Download 'The Iliad' from gutenberg.org.wcout << L"Downloading 'The Iliad'..." << endl;wstring file = get_http_file(session, L"http://www.gutenberg.org/files/6130/6130-0.txt");wcout << endl;// Convert the text to a list of individual words.vector<wstring> words;make_word_list(file, words);// Compare the time that it takes to perform several operations on the data// serially and in parallel.__int64 elapsed;vector<pair<wstring, size_t>> common_words;vector<wstring> longest_sequence;   vector<pair<wstring, wstring>> palindromes;wcout << L"Running serial version...";elapsed = time_call([&] {common_words = find_common_words(words, 5, 9);longest_sequence = find_longest_sequence(words);palindromes = find_palindromes(words, 5);});wcout << L" took " << elapsed << L" ms." << endl;wcout << L"Running parallel version...";elapsed = time_call([&] {parallel_invoke(         [&] { common_words = find_common_words(words, 5, 9); },[&] { longest_sequence = find_longest_sequence(words); },[&] { palindromes = find_palindromes(words, 5); });});wcout << L" took " << elapsed << L" ms." << endl;wcout << endl;// Print results.wcout << L"The most common words that have five or more letters are:" << endl;for_each(begin(common_words), end(common_words), [](const pair<wstring, size_t>& p) {wcout << L"   " << p.first << L" (" << p.second << L")" << endl; });wcout << L"The longest sequence of words that have the same first letter is:" << endl << L"   ";for_each(begin(longest_sequence), end(longest_sequence), [](const wstring& s) {wcout << s << L' '; });wcout << endl;wcout << L"The following palindromes appear in the text:" << endl;for_each(begin(palindromes), end(palindromes), [](const pair<wstring, wstring>& p) {wcout << L"   "  << p.first << L" " << p.second << endl;});
}// Downloads the file at the given URL.
CString get_http_file(CInternetSession& session, const CString& url)
{CString result;// Reads data from an HTTP server.CHttpFile* http_file = NULL;try{// Open URL.http_file = reinterpret_cast<CHttpFile*>(session.OpenURL(url, 1));// Read the file.if(http_file != NULL){           UINT bytes_read;do{char buffer[10000];bytes_read = http_file->Read(buffer, sizeof(buffer));result += buffer;}while (bytes_read > 0);}}catch (CInternetException){// TODO: Handle exception}// Clean up and return.delete http_file;return result;
}// Adds each word in the provided string to the provided vector of strings.
void make_word_list(const wstring& text, vector<wstring>& words)
{// Add continuous sequences of alphanumeric characters to the // string vector. wstring current_word;for_each(begin(text), end(text), [&](wchar_t ch) {if (!iswalnum(ch)){if (current_word.length() > 0){words.push_back(current_word);current_word.clear();}}else{current_word += ch;}});
}// Finds the most common words whose length are greater than or equal to the 
// provided minimum. 
vector<pair<wstring, size_t>> find_common_words(const vector<wstring>& words, size_t min_length, size_t count)
{typedef pair<wstring, size_t> pair;// Counts the occurrences of each word.map<wstring, size_t> counts;for_each(begin(words), end(words), [&](const wstring& word) {// Increment the count of words that are at least the minimum length.if (word.length() >= min_length){auto find = counts.find(word);if (find != end(counts))find->second++;elsecounts.insert(make_pair(word, 1));}});// Copy the contents of the map to a vector and sort the vector by// the number of occurrences of each word.vector<pair> wordvector;copy(begin(counts), end(counts), back_inserter(wordvector));sort(begin(wordvector), end(wordvector), [](const pair& x, const pair& y) {return x.second > y.second;});size_t size = min(wordvector.size(), count);wordvector.erase(begin(wordvector) + size, end(wordvector));return wordvector;
}// Finds the longest sequence of words that have the same first letter.
vector<wstring> find_longest_sequence(const vector<wstring>& words)
{// The current sequence of words that have the same first letter.vector<wstring> candidate_list;// The longest sequence of words that have the same first letter.vector<wstring> longest_run;for_each(begin(words), end(words), [&](const wstring& word) {// Initialize the candidate list if it is empty.if (candidate_list.size() == 0){candidate_list.push_back(word);}// Add the word to the candidate sequence if the first letter// of the word is the same as each word in the sequence.else if (word[0] == candidate_list[0][0]){candidate_list.push_back(word);}// The initial letter has changed; reset the candidate list.else {// Update the longest sequence if needed.if (candidate_list.size() > longest_run.size())longest_run = candidate_list;candidate_list.clear();candidate_list.push_back(word);         }});return longest_run;
}// Finds all pairs of palindromes that appear in the provided collection
// of words.
vector<pair<wstring, wstring>> find_palindromes(const vector<wstring>& words, size_t min_length)
{typedef pair<wstring, wstring> pair;vector<pair> result;// Copy the words to a new vector object and sort that vector.vector<wstring> wordvector;copy(begin(words), end(words), back_inserter(wordvector));sort(begin(wordvector), end(wordvector));// Add each word in the original collection to the result whose palindrome // also exists in the collection. for_each(begin(words), end(words), [&](const wstring& word) {if (word.length() >= min_length){wstring rev = word;reverse(begin(rev), end(rev));if (rev != word && binary_search(begin(wordvector), end(wordvector), rev)){auto candidate1 = make_pair(word, rev);auto candidate2 = make_pair(rev, word);if (find(begin(result), end(result), candidate1) == end(result) &&find(begin(result), end(result), candidate2) == end(result))result.push_back(candidate1);}}});return result;
}

此示例生成以下示例输出。

Downloading 'The Iliad'...Running serial version... took 953 ms.
Running parallel version... took 656 ms.The most common words that have five or more letters are:their (953)shall (444)which (431)great (398)Hector (349)Achilles (309)through (301)these (268)chief (259)
The longest sequence of words that have the same first letter is:through the tempest to the tented
The following palindromes appear in the text:spots stopsspeed deepskeels sleek

该示例使用 parallel_invoke 算法调用对同一数据源执行操作的多个函数。 可以使用 parallel_invoke 算法并行调用任意函数集,而不仅仅是对相同数据执行操作的函数集。

由于 parallel_invoke 算法并行调用每个工作函数,因此其性能受完成时间最长的函数的限制(即如果运行时在单独的处理器上处理每个函数)。 如果此示例并行执行的任务数超过可用的处理器数量,则每个处理器上可以运行多个任务。 在这种情况下,性能受完成时间最长的任务组的限制。

由于此示例并行执行三个任务,因此不应期望在具有三个以上处理器的计算机上缩放性能。 为了提高性能,可以将运行时间最长的任务分解为较小的任务,并行运行这些任务。

如果你无需取消支持,则可以使用 parallel_invoke 算法而不是 concurrency::task_group 和 concurrency::structured_task_group 类。 

编译代码

若要编译代码,请复制代码并将其粘贴到 Visual Studio 项目中,或粘贴到一个名为 parallel-word-mining.cpp 的文件中,然后在 Visual Studio 命令提示符窗口中运行以下命令。

cl.exe /EHsc /MD /DUNICODE /D_AFXDLL parallel-word-mining.cpp

http://www.mrgr.cn/news/24054.html

相关文章:

  • MySQL聚合统计:性能优化与高级应用
  • C++之结构体
  • 【有啥问啥】探索扫地机器人中的 SLAM 算法:原理、实现与未来展望
  • 9.10javaweb项目总结
  • 国产ERT/ECT工业电阻/电容层析成像系统在多相流领域的应用
  • C++设计模式——Mediator中介者模式
  • Python 之正则表达式(Regular Expressions in Python)
  • 使用ESP8266和OLED屏幕实现一个小型电脑性能监控
  • Matlab simulink建模与仿真 第十二章(信号属性库)
  • 1. 初识LLM API:环境配置与多轮对话演示
  • MySQL学习(多表操作)
  • 【有啥问啥】CPU架构(ISA)详解:发展历程、种类与应用
  • 193页WORD省级智慧高速公路投标技术方案
  • 算法岗/开发岗 实况
  • 单例模式的学习
  • gradle 学习备忘
  • C++11(2)
  • JsonCpp源码分析——Reader
  • Java 访问修饰符详解:public、private、protected 及默认访问权限
  • 06_自平衡二叉搜索树