Golang中的地图访问瓶颈

时间:2014-01-10 20:47:01

标签: data-structures go hashmap

我正在使用Golang为具有超过30000个可能标记的数据集实现朴素贝叶斯分类。我建立了模型,我处于分类阶段。我正在分类1000条记录,这需要花费5分钟。我用pprof功能描述了代码; top10如下所示:

Total: 28896 samples
   16408  56.8%  56.8%    24129  83.5% runtime.mapaccess1_faststr
    4977  17.2%  74.0%     4977  17.2% runtime.aeshashbody
    2552   8.8%  82.8%     2552   8.8% runtime.memeqbody
    1468   5.1%  87.9%    28112  97.3% main.(*Classifier).calcProbs
     861   3.0%  90.9%      861   3.0% math.Log
     435   1.5%  92.4%      435   1.5% runtime.markspan
     267   0.9%  93.3%      302   1.0% MHeap_AllocLocked
     187   0.6%  94.0%      187   0.6% runtime.aeshashstr
     183   0.6%  94.6%     1137   3.9% runtime.mallocgc
     127   0.4%  95.0%      988   3.4% math.log10

令人惊讶的是,地图访问似乎是瓶颈。有没有人经历过这个。还有什么其他关键的,有价值的数据结构可以用来避免这个瓶颈?所有地图访问都在下面给出的代码中完成:

func (nb *Classifier) calcProbs(data string) *BoundedPriorityQueue{
    probs := &BoundedPriorityQueue{} 
    heap.Init(probs)

    terms := strings.Split(data, " ")
    for class, prob := range nb.classProb{
        condProb := prob
        clsProbs := nb.model[class]
        for _, term := range terms{
            termProb := clsProbs[term]
            if termProb != 0{
                condProb += math.Log10(termProb)
            }else{
                condProb += -6 //math.Log10(0.000001)
            }
        }
       entry := &Item{
            value: class,
            priority: condProb,
        }
        heap.Push(probs,entry)
    }
    return probs
}

地图是nb.classProb,它是map[string]float64,而nb.model是类型为

的嵌套地图
map[string]map[string]float64

2 个答案:

答案 0 :(得分:3)

除了@tomwilde所说的,可以加速你的算法的另一种方法是字符串实习。也就是说,如果您提前知道密钥域,则可以完全避免使用映射。我写了一个小包,为你做string interning

答案 1 :(得分:2)

是的,地图访问将成为此代码中的瓶颈:它是两个嵌套循环中最重要的操作。

无法从代码中确定您已包含的内容,但我希望您的课程数量有限。您可能会做的是对它们进行编号,并存储类似术语的类概率:

map[string][NumClasses]float64

(即:对于每个术语,存储一组分类概率[或者可能已经预先计算了它们的日志],而NumClasses是您拥有的不同类的数量)。

然后,首先迭代术语,然后在里面迭代。昂贵的地图查找将在外部循环中完成,内部循环将在数组上进行迭代。

这将减少NumClasses因子的地图查找次数。如果您的数据非常稀疏,这可能需要更多内存。

下一个优化是使用多个goroutine进行计算,假设您有多个CPU核心可用。