我有一个大文件,我必须通过块读取它。每次当我读取一个块时,我都要做一些耗时的操作,所以我认为多线程读取可能有所帮助,每个线程逐个读取一个块并进行操作。这是我在c ++ 11中的代码
#include<iostream>
#include<fstream>
#include <condition_variable>
#include <mutex>
#include <thread>
using namespace std;
const int CHAR_PER_FILE = 1e8;
const int NUM_THREAD = 2;
int order = -1;
bool is_reading = false;
mutex mtx;
condition_variable file_not_reading;
void partition(ifstream& is)
{
while (is.peek() != EOF)
{
unique_lock<mutex> lock(mtx);
while (is_reading)
file_not_reading.wait(lock);
is_reading = true;
char *c = new char[CHAR_PER_FILE];
is.read(c, CHAR_PER_FILE);
order++;
is_reading = false;
file_not_reading.notify_all();
lock.unlock();
char oc[3];
sprintf(oc, "%d", order);
this_thread::sleep_for(chrono::milliseconds(2000));//some operations that take long time
ofstream os(oc, ios::binary);
os.write(c, CHAR_PER_FILE);
delete[] c;
os.close();
}
}
int main()
{
ifstream is("bigfile.txt",ios::binary);
thread threads[NUM_THREAD];
for (int i = 0; i < NUM_THREAD; i++)
threads[i] = thread(partition, ref(is));
for (int i = 0; i < NUM_THREAD; i++)
threads[i].join();
is.close();
system("pause");
return 0;
}
但是我的代码没有用,它只创建了4个文件而不是`bigfilesize / CHAR_PER_FILE,并且线程似乎卡住了,我怎么能让它工作?
是否有任何c ++ 11多线程读取文件实现或示例?
感谢。
答案 0 :(得分:5)
我的建议:
答案 1 :(得分:1)
您可以将基于任务的并行性与std :: async:
结合使用class result; // result of expensive operation
result expensive_operation(std::vector<char> const& data)
{
result r = // long computation
return r;
}
std::vector<char>::size_type BLOCK_SIZE = 4096;
std::vector<std::future<result>> partition(ifstream& in)
{
std::vector<std::future<result>> tasks;
while (!in.eof() && !in.fail())
{
std::vector<char> c(BLOCK_SIZE);
is.read(c.data(), BLOCK_SIZE);
c.resize(in.gcount());
tasks.push_back( std::async( [](std::vector<char> data)
{
return expensive_operation(data);
},
std::move(c) ));
}
return tasks;
}
int main()
{
ifstream is("bigfile.txt",ios::binary);
auto results = partition(is);
// iterate over results and do something with it
}
答案 2 :(得分:0)
是否必须以“顺序”顺序读取文件,即必须按特殊顺序“操作”块?否则你可以例如制作4个线程,让每个线程读取文件的1/4(你可以通过使用tellg并在例如向量或变量中保存位置来实现)。这样你就不必使用锁。
也许您可以告诉我们您所阅读的数据是如何评估的。
答案 3 :(得分:0)
...也许
void partition(ifstream& is)
{
unique_lock<mutex> lock(mtx);
std::vector<char> c(CHAR_PER_FILE);
is.read(c.data(), CHAR_PER_FILE);
lock.unlock();
if (is.fail() && !is.eof()) return;
size_t num_bytes_read = is.gcount();
std::ostringstream oc;
oc << order;
this_thread::sleep_for(chrono::milliseconds(2000)); //take long time
if (std::ofstream os(oc, ios::binary))
os.write(c.data(), CHAR_PER_FILE);
}
注意:
互斥锁已将操作序列化 - 不需要条件变量。
我添加了一点输入错误和字节读取处理 - 您应该在os.write()
之后检查,为失败的else
创建添加ofstream
等。