在C++中从距离矩阵创建索引向量的最快方法
Fastest way to create a vector of indices from distance matrix in C++
我有一个大小
D
n
n
的距离矩阵和一个常量L
作为输入。我需要创建一个包含D
中所有条目v
使其值最多L
的向量。这里的v
必须按特定顺序排列v = [v1 v2 .. vn]
其中vi
包含i
D
行中的条目,其值最多为L
。每个vi
中的条目顺序并不重要。
我想知道有一种快速的方法可以使用向量、数组或任何数据结构 + parallization 创建v
。我所做的是用于循环,对于大n
来说非常慢。
vector<int> v;
for (int i=0; i < n; ++i){
for (int j=0; j < n; ++j){
if (D(i,j) <= L) v.push_back(j);
}
}
最好的方法主要取决于上下文。如果您正在寻找GPU对偶化,您应该看看OpenCL。
对于基于 CPU 的对偶化,C++标准#include <thread>
库可能是最好的选择,但您需要小心:
- 线程需要时间来创建,所以如果 n 相对较小(<1000 左右(,它会减慢您的速度
- D(i,j( 必须同时由多个线程读取
- v 必须可由多个线程写入,标准向量不会削减它
v 可以是以 vi 作为其子向量的 2D 向量,但这些必须在平行化之前初始化:
std::vector<std::vector<int>> v;
v.reserve(n);
for(size_t i = 0; i < n; i++)
{
v.push_back(std::vector<int>());
}
您需要决定要使用的线程数。如果这仅适用于一台计算机,则硬编码是一个有效的选项。线程库中有一个函数可以获取支持的线程数量,但它更像是一个提示而不是可信。
size_t threadAmount = std::thread::hardware_concurrency(); //How many threads should run hardware_concurrency() gives you a hint, but its not optimal
std::vector<std::thread> t; //to store the threads in
t.reserve(threadAmount-1); //you need threadAmount-1 extra threads (we already have the main-thread)
要启动线程,您需要一个可以执行的函数。在这种情况下,这是通读矩阵的一部分。
void CheckPart(size_t start, size_t amount, int L, std::vector<std::vector<int>>& vec)
{
for(size_t i = start; i < amount+start; i++)
{
for(size_t j = 0; j < n; j++)
{
if(D(i,j) <= L)
{
vec[i].push_back(j);
}
}
}
}
现在,您需要将矩阵拆分为大约 n/threadAmount 行的部分并启动线程。线程构造函数需要一个函数及其参数,但它将始终尝试复制参数,即使函数需要引用也是如此。为了防止这种情况,您需要强制使用带有std::ref()
int i = 0;
int rows;
for(size_t a = 0; a < threadAmount-1; a++)
{
rows = n/threadAmount + ((n%threadAmount>a)?1:0);
t.push_back(std::thread(CheckPart, i, rows, L, std::ref(v)));
i += rows;
}
线程现在正在运行,所要做的就是在主函数上运行最后一个块:
SortPart(i, n/threadAmount, L, v);
之后,您需要等待线程完成并清理它们:
for(unsigned int a = 0; a < threadAmount-1; a++)
{
if(t[a].joinable())
{
t[a].join();
}
}
请注意,这只是一个快速而肮脏的例子。不同的问题可能需要不同的实现,而且由于我无法猜测上下文,因此我能提供的帮助相当有限。
考虑到这些评论,我作了适当的更正(强调(。
您是否搜索过编写性能代码、线程、asm 指令(如果您的程序集不完全是您想要的(和用于并行处理的 OpenCL 的技巧?如果没有,我强烈建议!
在某些情况下,在 for 循环之外声明所有 for 循环变量(以避免多次声明它们(会使它更快,但在这种情况下并非如此(我们的朋友 Paddy 的评论(。
此外,使用new
而不是vector
可以更快,正如我们在这里看到的:在C++中使用数组或 std::vectors,性能差距是什么? -我测试了一下,用vector
比new
慢 6 秒,只需要 1 秒。我想当有人搜索性能时,不需要 std::vector 附带的安全性和易于管理保证,即使因为使用new
不是那么困难,只需避免堆溢出计算并记住使用delete[]
user4581301 在这里是正确的,以下陈述是不正确的:最后,如果你在数组而不是矩阵中构建D
(或者如果你D
复制到一个常量数组中,也许......(,它将对缓存非常友好,并将保存一个 for 循环语句。
- 在C++中调整向量中的索引
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 将转换字符键入 int 以用作向量C++的索引
- 在对向量中查找元素的索引
- 如何检查类实例向量的索引是否为空
- 如何根据排序索引的向量对 std::index 集进行排序?
- 向量索引变量声明(size_t 或 std::vector<DATATYPE>::size_type)
- 访问向量索引C++
- 包含全局最小值的向量索引
- C 向量由另一个向量索引
- 向量索引在C 中不会包裹吗?什么是解决方法
- 使用Armadillo库中的指数向量索引矩阵
- 将多个整数添加到一个向量索引? 'Cout'不起作用
- array:将一维数组的索引转换为多维数组的向量索引
- 将一维"flattened"索引转换为 N 维数组的 N 维向量索引
- 向量索引访问与迭代器访问的效率
- 特征矩阵支持由向量索引吗?
- 如何重写由向量索引指向的项?
- 在另一个向量中引用向量索引时出错:'std::out_of_range at memory location'
- c++帮助传递向量索引到函数