我们可以为SparseMatrix实现做的最好的事情是什么?

时间:2012-03-10 17:03:04

标签: c++ matrix

我使用的是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)

1 个答案:

答案 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++