C++ 中有效的 wordcount 多线程
Effective wordcount multithreading in C++
我对 C++ 和多线程还很陌生,需要一些帮助来创建一个有效地在多个线程之间划分工作的字数统计。
假设,我有一个计算一行(字符串)中单词的函数:
count_words_in_line(line);
对于一个线程,行中的总字数是该函数输出的每一行的简单总和,但我如何将其划分为线程?
我的想法是使用两个线程 - 一个用于计算偶数行,一个用于计算奇数行,但是代码导致了分段错误。
我做错了什么?有没有更好的方法?
我不想使用线程池,理想情况下希望在参数中指定线程数,以便衡量多线程实现的性能。
这是我的相关代码:
bool odd = true;
auto thread_count_odd = [&counter, &infile, &odd, &line, &mutex]() {
while (std::getline(infile, line)) {
if (odd) {
std::cout<<"Count odd"<<std::endl;
mutex.lock();
counter += count_words_in_line(line);
mutex.unlock();
}
odd = !odd;
}
};
bool even = false;
auto thread_count_even = [&counter, &infile, &even, &line, &mutex]() {
while (std::getline(infile, line)) {
if (even) {
std::cout<<"Count even"<<std::endl;
mutex.lock();
counter += count_words_in_line(line);
mutex.unlock();
}
even = !even;
}
};
std::thread t1(thread_count_odd);
std::thread t2(thread_count_even);
t1.join();
t2.join();
- 使用 read-index/write-index 和 mutex/condition-variable 的共享向量(如 Jarod42 所建议)。
- 启动计数线程,等待写入索引大于读取索引。
- 让主线程读入行并填充向量并相应地通知条件变量。
- 当计数线程看到写入索引增加时,它们可以读取行并进行计数。
- 主线程表示文件读取完毕。计数线程 return 由
join()
传递的结果。所以可以添加结果。
备注:可能只有一个线程会进行计数,这表明不需要其他线程。至少有2个线程:读取线程和处理线程。
我认为问题是您必须在 getline 调用周围有一个互斥量。两个线程同时访问 infile,这可能会导致问题。
我有这段代码可以使用条件变量来满足您的情况。希望这有帮助
`
#include<iostream>
#include<thread>
#include<string>
#include<mutex>
#include<condition_variable>
#include<unistd.h>
#include <fstream>
#define MAX_THREADS 50
using namespace std;
thread *threads = new thread[MAX_THREADS];
condition_variable cv[MAX_THREADS];
mutex m1;
int counter=0;
int count_words_in_line(string line){
/*write your code here*/
return 1;
}
void printString(int tid, ifstream &inFile, int tcount)
{
unique_lock<mutex> lock(m1);
while(1)
{
string line;
inFile >> line;
string a = "";
if(line==a)break;
cv[(tid+1)%tcount].notify_one();
cv[tid].wait(lock);
counter += count_words_in_line(line);
}
cv[(tid+1)%tcount].notify_one();
}
int main(int argc, char** argv)
{
int tcount, ccount, k;
std::ifstream inFile;
string name;
inFile.open("input.txt");
string str;
tcount = 2;
for(int i = 0; i < tcount; i++) {
threads[i] = thread(printString, i, ref(inFile), tcount);
}
for (int i = 0; i < tcount; i++)
threads[i].join();
cout << counter << endl;
return 0;
}
`
我对 C++ 和多线程还很陌生,需要一些帮助来创建一个有效地在多个线程之间划分工作的字数统计。
假设,我有一个计算一行(字符串)中单词的函数:
count_words_in_line(line);
对于一个线程,行中的总字数是该函数输出的每一行的简单总和,但我如何将其划分为线程?
我的想法是使用两个线程 - 一个用于计算偶数行,一个用于计算奇数行,但是代码导致了分段错误。
我做错了什么?有没有更好的方法?
我不想使用线程池,理想情况下希望在参数中指定线程数,以便衡量多线程实现的性能。
这是我的相关代码:
bool odd = true;
auto thread_count_odd = [&counter, &infile, &odd, &line, &mutex]() {
while (std::getline(infile, line)) {
if (odd) {
std::cout<<"Count odd"<<std::endl;
mutex.lock();
counter += count_words_in_line(line);
mutex.unlock();
}
odd = !odd;
}
};
bool even = false;
auto thread_count_even = [&counter, &infile, &even, &line, &mutex]() {
while (std::getline(infile, line)) {
if (even) {
std::cout<<"Count even"<<std::endl;
mutex.lock();
counter += count_words_in_line(line);
mutex.unlock();
}
even = !even;
}
};
std::thread t1(thread_count_odd);
std::thread t2(thread_count_even);
t1.join();
t2.join();
- 使用 read-index/write-index 和 mutex/condition-variable 的共享向量(如 Jarod42 所建议)。
- 启动计数线程,等待写入索引大于读取索引。
- 让主线程读入行并填充向量并相应地通知条件变量。
- 当计数线程看到写入索引增加时,它们可以读取行并进行计数。
- 主线程表示文件读取完毕。计数线程 return 由
join()
传递的结果。所以可以添加结果。
备注:可能只有一个线程会进行计数,这表明不需要其他线程。至少有2个线程:读取线程和处理线程。
我认为问题是您必须在 getline 调用周围有一个互斥量。两个线程同时访问 infile,这可能会导致问题。
我有这段代码可以使用条件变量来满足您的情况。希望这有帮助
`
#include<iostream>
#include<thread>
#include<string>
#include<mutex>
#include<condition_variable>
#include<unistd.h>
#include <fstream>
#define MAX_THREADS 50
using namespace std;
thread *threads = new thread[MAX_THREADS];
condition_variable cv[MAX_THREADS];
mutex m1;
int counter=0;
int count_words_in_line(string line){
/*write your code here*/
return 1;
}
void printString(int tid, ifstream &inFile, int tcount)
{
unique_lock<mutex> lock(m1);
while(1)
{
string line;
inFile >> line;
string a = "";
if(line==a)break;
cv[(tid+1)%tcount].notify_one();
cv[tid].wait(lock);
counter += count_words_in_line(line);
}
cv[(tid+1)%tcount].notify_one();
}
int main(int argc, char** argv)
{
int tcount, ccount, k;
std::ifstream inFile;
string name;
inFile.open("input.txt");
string str;
tcount = 2;
for(int i = 0; i < tcount; i++) {
threads[i] = thread(printString, i, ref(inFile), tcount);
}
for (int i = 0; i < tcount; i++)
threads[i].join();
cout << counter << endl;
return 0;
}
`