我有一个包含向量向量的数据结构,每个向量包含大约~16000000个双值。
我现在想要对这些向量进行中值组合,这意味着每个原始向量我在第i个位置取值,计算这些值的中值,然后将它们存储在位置i的结果向量中。
我已经有了直截了当的解决方案,但速度令人难以置信:
vector< vector<double> > vectors; //vectors contains the datavectors
vector<double> tmp;
vector<double> result;
vector<double> tmpmedian;
double pixels = 0.0;
double matrixcount = vectors.size();
tmp = vectors.at(0);
pixels = tmp.size();
for (int i = 0; i < pixels; i++) {
for (int j = 0; j < matrixcount; j++) {
tmp = vectors.at(j);
tmpmedian.push_back(tmp.at(i));
}
result.push_back(medianOfVector(tmpmedian));
tmpmedian.clear();
}
return result;
且medianOfVector看起来像这样:
double result = 0;
if ((vec.size() % 2) != 0) {
vector<double>::iterator i = vec.begin();
vector<double>::size_type m = (vec.size() / 2);
nth_element(i, i + m, vec.end());
result = vec.at(m);
} else {
vector<double>::iterator i = vec.begin();
vector<double>::size_type m = (vec.size() / 2) - 1;
nth_element(i, i + m, vec.end());
result = (vec.at(m) + vec.at(m + 1)) / 2;
}
return result;
我有一种算法或方法可以更快地完成这项任务,这需要几乎永恒的时间。
编辑:感谢您的回复,如果有人对此感兴趣是固定版本,现在需要大约9秒将三个向量与~16000000个元素组合在一起,平均组合需要大约3秒:
vector< vector<double> > vectors; //vectors contains the datavectors
vector<double> *tmp;
vector<double> result;
vector<double> tmpmedian;
tmp = &vectors.at(0);
int size = tmp->size();
int vectorsize = vectors.size();
for (int i = 0; i < size; i++) {
for (int j = 0; j < vectorsize; j++) {
tmp = &vectors.at(j);
tmpmedian.push_back(tmp->at(i));
}
result.push_back(medianOfVector(tmpmedian));
tmpmedian.clear();
}
return result;
且medianOfVector:
double result = 0;
if ((vec.size() % 2) != 0) {
vector<double>::iterator i = vec.begin();
vector<double>::size_type m = (vec.size() / 2);
nth_element(i, i + m, vec.end());
result = vec.at(m);
} else {
vector<double>::iterator i = vec.begin();
vector<double>::size_type m = (int) (((vec.size() - 1) / 2));
nth_element(i, i + m, vec.end());
double min = vec.at(m);
double max = *min_element(i + m + 1, vec.end());
result = (min + max) / 2;
}
return result;
}
答案 0 :(得分:4)
有两点,都源于你将tmp
定义为向量而不是(例如)引用的事实。
vector<double> tmp;
tmp = vectors.at(0);
pixels = tmp.size();
您只需将vectors[0]
的全部内容复制到tmp
中即可提取尺寸。你几乎可以通过避免副本获得一些速度:
pixels = vectors.at(0).size();
不是为了获得它的大小而复制整个向量,而是只获得第一个向量的引用,并获得该现有向量的大小。
for (int i = 0; i < pixels; i++) {
for (int j = 0; j < matrixcount; j++) {
tmp = vectors.at(j);
tmpmedian.push_back(tmp.at(i));
}
在此,您再次将vectors.at(j)
的全部内容复制到tmp
。但是(再次)你并不需要所有数据的新副本 - 你只是从该副本中检索单个项目。您可以直接从原始向量检索所需的数据,而无需复制整个内容:
tmpmedian.push_back(vectors.at(j).at(i));
可能的下一步是从使用.at
切换到operator[]
:
tmpmedian.push_back(vectors[j][i]);
这更多是一种权衡 - 它不太可能获得几乎同样多的收益,并且在此过程中失去了一点安全性(范围检查)。为了避免失去安全性,您可以考虑(例如)使用基于范围的for
循环而不是当前代码中计数的for
循环。
沿着相当不同的线条,您可以改为从使用vector<vector<double>>
更改为使用围绕矢量的小包装器将2D寻址转换为单个矢量。使用适当的列式迭代器,您可以避免创建tmpmedian
基本上是原始2D矩阵的列的副本 - 而是,您将列式迭代器传递给{{1并且只是就地遍历原始数据的列。