我使用的是Eigen矩阵框架和SparseVector库。我遇到了性能问题,我需要的是稀疏矢量点积。所以我推出了自己的SparseMatrix实现,希望它能以某种方式更快一点:
一些示例代码:
#include <map>
using namespace std ;
struct SparseMatrix
{
map<int, Vector> vals ;
Vector dot( SparseMatrix& o )
{
SparseMatrix *LS, *RS ;
// iterate over the smaller of the 2
if( vals.size() < o.vals.size() )
{
// walk vals
LS = this ;
RS = &o ;
}
else
{
LS = &o ;
RS = this ;
}
// walk LS
Vector sum = 0 ;
for( map<int,Vector>::iterator LSIter = LS->vals.begin() ; LSIter != LS->vals.end() ; ++LSIter )
{
const int& key = LSIter->first ;
// use the key, see if RS has a similar entry.
map<int,Vector>::iterator RSIter = RS->vals.find( key );
if( RSIter != RS->vals.end() )
sum += RSIter->second * LSIter->second ;
}
return sum ;
}
} ;
所以2个向量的点积,比如说有条目:
+---------------+ | vec 1 | | index value | | 2 18 | | 7 4 | | 18 33 | +---------------+ +---------------+ | vec 2 | | index value | | 2 1 | | 15 87 | | 21 92 | +---------------+
点积为18。
所以,你可以看到我使用std::map
进行元素查找,以查看一个向量中的元素是否在另一个向量中。
由于我只使用整数索引和1d数组,有没有办法让查询更快?我的稀疏矩阵乘法仍然是一个瓶颈(我的代码的性能仅略微快于Eigen)
答案 0 :(得分:3)
有一对矢量:index - &gt;值,按索引排序。然后立即迭代两个向量。如果你有两个相同的索引,乘以值,将其添加到结果并转到两个向量中的下一对。另外,对向的第一个元素较小的向量上的递增迭代索引。
当然,假设您没有大量修改数据。
即。在伪代码中:
for i = 0, j = 0; i < vec1.size && j < vec2.size:
if vec1[i].first == vec2[j].first:
result += vec1[i++].second * vec2[j++].second
elif vec1[i].first < vec2[j].first:
i++
else
j++