考虑以下代码:
std::vector<int> indices = /* Non overlapping ranges. */;
std::istream& in = /*...*/;
for(std::size_t i= 0; i< indices.size()-1; ++i)
{
in.seekg(indices[i]);
std::vector<int> data(indices[i+1] - indices[i]);
in.read(reinterpret_cast<char*>(data.data()), data.size()*sizeof(int));
process_data(data);
}
我想让这段代码尽可能快地并行。
使用PPL将其并行化的一种方法是:
std::vector<int> indices = /* Non overlapping ranges. */;
std::istream& in = /*...*/;
std::vector<concurrency::task<void>> tasks;
for(std::size_t i= 0; i< indices.size()-1; ++i)
{
in.seekg(indices[i]);
std::vector<int> data(indices[i+1] - indices[i]);
in.read(reinterpret_cast<char*>(data.data()), data.size()*sizeof(int));
tasks.emplace_back(std::bind(&process_data, std::move(data)));
}
concurrency::when_all(tasks.begin(), tasks.end()).wait();
这种方法的问题是我想在同一个线程中处理数据(适合 CPU 缓存),因为它被读入内存(数据在缓存中很热),这不是这里的情况,它只是浪费了使用热数据的机会。
我有两个想法如何改进这一点,但是,我也无法实现。
在单独的任务上开始下一次迭代。
/* ??? */ { in.seekg(indices[i]); std::vector<int> data(indices[i+1] - indices[i]); // data size will fit into CPU cache. in.read(reinterpret_cast<char*>(data.data()), data.size()*sizeof(int)); /* Start a task that begins the next iteration? */ process_data(data); }
使用内存映射文件并映射文件的所需区域,而不是仅仅从具有正确偏移量的指针中读取。使用 处理数据范围
parallel_for_each
。但是,我不了解内存映射文件在何时读取到内存和缓存注意事项方面的性能影响。也许我什至不必考虑缓存,因为文件只是 DMA:d 到系统内存,从不通过 CPU?
有什么建议或意见吗?