use*_*134 0 c++ double vector median
我有一个包含向量向量的数据结构,每个向量由大约 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;
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
我有一种算法或方法可以更快地做到这一点,但它几乎需要永恒的时间才能完成。
编辑:谢谢您的回复,如果有人感兴趣,这里是固定版本,现在将三个向量与约 16000000 个元素进行中值组合需要大约 9 秒,平均组合需要大约 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;
Run Code Online (Sandbox Code Playgroud)
和中值向量:
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;
}
Run Code Online (Sandbox Code Playgroud)
有几点,都源于您定义tmp为向量而不是(例如)引用的事实。
vector<double> tmp;
tmp = vectors.at(0);
pixels = tmp.size();
Run Code Online (Sandbox Code Playgroud)
在这里,您将整个内容复制vectors[0]到tmp只是为了提取大小。通过避免复制,您几乎肯定会获得一些速度:
pixels = vectors.at(0).size();
Run Code Online (Sandbox Code Playgroud)
这不是复制整个向量来获取其大小,而是获取对第一个向量的引用,并获取该现有向量的大小。
for (int i = 0; i < pixels; i++) {
for (int j = 0; j < matrixcount; j++) {
tmp = vectors.at(j);
tmpmedian.push_back(tmp.at(i));
}
Run Code Online (Sandbox Code Playgroud)
在这里,您再次将整个内容复制vectors.at(j)到tmp. 但是(再次)您实际上并不需要所有数据的新副本 - 您只是从该副本中检索单个项目。您可以直接从原始向量中检索所需的数据,而无需复制整个内容:
tmpmedian.push_back(vectors.at(j).at(i));
Run Code Online (Sandbox Code Playgroud)
下一步可能是从使用切换.at到operator[]:
tmpmedian.push_back(vectors[j][i]);
Run Code Online (Sandbox Code Playgroud)
但这更多的是一种权衡——它不太可能获得那么多的收益,并且在此过程中失去了一些安全性(范围检查)。为了避免失去安全性,您可以考虑(例如)在当前代码中使用基于范围的for循环而不是计数循环。for
按照相当不同的思路,您可以从使用 a 改为vector<vector<double>>使用向量周围的小包装器,将 2D 寻址提供给单个向量。将其与合适的按列迭代器结合使用,您可以避免创建tmpmedian原始二维矩阵列的副本 - 相反,您可以将按列迭代器传递给medianOfVector,然后只迭代原始二维矩阵的列数据到位。
| 归档时间: |
|
| 查看次数: |
691 次 |
| 最近记录: |