【问题标题】:What type of sparse vector should I use?我应该使用什么类型的稀疏向量?
【发布时间】:2019-04-23 20:47:04
【问题描述】:

数据

我有N 不同(排序的)索引向量(std::vector<unsigned int>)。索引在 [0; L-1]。以下是关于此数据的两条经验法则:

  • 只有大约 0.1% 到 10% 的可能索引存在于任何地方
  • 如果在给定向量中找到索引,则很可能会在其他向量中再次找到多次。

因此,带有N=10 向量和L = 200 的可能数据集可能是

{45, 110, 119, 145, 170}
{9, 45, 110, 145, 178, 170}
{45, 145}
{45, 178, 183}
{45, 53, 110, 170}
{9, 119, 123, 179}
{9, 45, 119, 130, 131, 170, 190, 199}
{9, 45, 110, 170, 199}
{31, 45, 145}
{9, 178, 183}

目标

我想计算每个索引的频率。我会做类似的事情

std::vector<double> computeFrequencies(std::vector<std::vector<unsigned int>>& data)
{
    assert(data.size() == N);

    std::vector<double> frequencies(L);
    for (unsigned Ni = 0 ; Ni < N ; Ni++)
    {
        for (unsigned i = 0 ; i < data[Ni].size() ; i++)
        {
            assert(data[Ni][i] < L)
            frequencies[data[Ni][i]]++;
        }
    }

    for (unsigned i = 0 ; i < L; i++)
    {
        frequencies[i] /= (double) N;
    }

    return(frequencies);    
}

然后我将再次循环通过函数computeFrequencies 返回的对象一次。

for (unsigned i = 0 ; i < L; i++)
{
    foo(frequencies[i]);
}

问题

对象frequencies 包含很多零,因此我应该使用稀疏向量。不过,我对稀疏矩阵的了解不多。我应该使用什么类型的稀疏向量?

我正在考虑使用boost::numeric::ublas::coordinate_matrix&lt;double&gt;&lt;double&gt;,因为当我遍历所有N 向量时,我会不断添加新的非零值,我认为坐标矩阵可以很好地处理这个问题。请注意,一般来说,对于这个函数,我更担心 RAM 的使用而不是计算时间。

【问题讨论】:

  • 由于您的操作系统在实际写入内存页面之前可能不会支持任何分配实际内存页面(至少 Linux 的默认设置),我想说不要担心。如果您想分配一个 TB 并且只写入几 GB,并且您写入的内容实际上适合内存,那么不要担心虚拟内存大小。除非您真正使用它,否则它不花钱。
  • 如果您只使用几 GB 的内存,那真的不值得大惊小怪,因为内存和计算之间的权衡通常是非常现实的。非常紧凑的结构往往更占用 CPU。非常稀疏的结构很容易访问。不过,如果您的结构非常稀疏,std::map 是一种选择。

标签: c++ data-structures containers sparse-matrix


【解决方案1】:

看起来稀疏向量表示不太适合您的问题。

按照您的描述完成任务:

  1. 将已排序的向量合并为一个已排序的向量。此处不时弹出如何进行高效的 K 路合并:merging N sorted files using K way merge
  2. 遍历新向量并计算每个条目的重复次数(很容易,因为它们都会在一起)以获取您的频率和foo 它们。

您甚至可以同时执行这两个步骤,完全避免将数据复制到新结构中。

【讨论】:

    猜你喜欢
    • 2015-06-29
    • 2017-03-26
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    相关资源
    最近更新 更多