我目前正在编写一个工具,它使用 STXXL 来查找硬盘驱动器上的大文件和驻留在 RAM 中的向量之间的相似之处。我在下面写了一个示例(适用于 Windows)来说明我的意思。引用的文件大约 38GB 大,是使用上述工具创建的。
在普通 HDD 和 SATA-SSD 上,它的性能相当不错,但在 M.2 或更快的 SSD 上,它最多只使用三分之一的带宽,即使它可以得到更多。
VS2017 Profiler 表明,
const_reference const_element(const blocked_index_type& offset) const
间接调用 STXXL 的函数
https://stxxl.org/tags/1.4.1/group__reqlayer.html#ga016f4e02b691aa4818ad3305de3f47bd
似乎是最慢的部分。有没有人知道为什么它表现不佳以及需要改变什么?
先感谢您。
编辑:新代码的性能表:
Threads CPU% SSD MB/s Time in s
8 72 450 265
6 64 560 286
4 52 720 329
2 29 790 600
1 17 900 1051
代码:
#include <inttypes.h>
#include <vector>
#include <random>
#include <ctime>
#include <limits>
#include <algorithm>
#include <tuple>
#include <chrono>
#include <stxxl/vector>
#include <stxxl/bits/io/wincall_file.h>
#include <omp.h>
using namespace std;
typedef stxxl::VECTOR_GENERATOR<tuple<uint32_t, uint32_t>, 16U, 16U, 4096 * 8, stxxl::RC>::result contentVecType;
int main() {
auto start = std::chrono::high_resolution_clock::now();
const string& sLibFile = "I:/DA/merged_s_80_h";
const int32_t& iNumOfThreads = 1, iNumOfVecs = 24;
const int32_t& iDiv = iNumOfVecs / iNumOfThreads;
omp_set_num_threads(iNumOfThreads);
ifstream fLibInfo(sLibFile + "_info.txt");
uint64_t iSizeOfLib = 0;
fLibInfo >> iSizeOfLib;
stxxl::wincall_file* stxxlLibFile = new stxxl::wincall_file(sLibFile, stxxl::file::RDONLY);
const contentVecType** vLib = new const contentVecType*[iNumOfThreads];
for (int32_t i = 0; i < iNumOfThreads; ++i) {
vLib[i] = new const contentVecType(stxxlLibFile, iSizeOfLib);
}
mt19937_64 rng(time(0));
uniform_int_distribution<uint32_t> unii(1, numeric_limits<uint32_t>::max());
vector<tuple<uint32_t,uint32_t>> vInput[24];
for (int32_t i = 0; i < iNumOfVecs; ++i) {
for (int32_t j = 0; j < 100000; ++j) {
vInput[i].push_back(make_tuple(unii(rng),0));
}
}
#pragma omp parallel for
for (int32_t i = 0; i < iNumOfVecs; ++i) {
sort(vInput[i].begin(), vInput[i].end());
}
#pragma omp parallel for
for (int32_t i = 0; i < iNumOfThreads; ++i) {
for (int32_t j = i* iDiv; j < (i+1)*iDiv; ++j) {
vector<tuple<uint32_t, uint32_t>> vDummy(vInput[j].size());
set_intersection(vInput[j].cbegin(), vInput[j].cend(), vLib[i]->cbegin(), vLib[i]->cend(), vDummy.begin(), [](const tuple<uint32_t, uint32_t>& a, const tuple<uint32_t, uint32_t>& b) { return get<0>(a) < get<0>(b); });
}
}
for (int32_t i = 0; i < iNumOfThreads; ++i) {
delete vLib[i];
}
delete[] vLib;
delete stxxlLibFile;
auto end = std::chrono::high_resolution_clock::now();
cout << "Time: " << chrono::duration_cast<std::chrono::seconds>(end - start).count() << endl;
return 0;
}