我在一个 3.0GB 的 CSV 文件中有 292 万个数据点,我需要遍历它两次以创建一个我想加载到 NetworkX 中的图形。按照目前的速度,生成这张图需要几天时间。我怎样才能加快速度?

similarity = 8 
 
graph = {} 
topic_pages = {} 
 
CSV.foreach("topic_page_node_and_edge.csv") do |row| 
                topic_pages[row[0]] = row[1..-1] 
end 
 
CSV.open("generate_graph.csv", "wb") do |csv| 
        i = 0 
        topic_pages.each do |row| 
                i+=1 
                row = row.flatten 
                topic_pages_attributes = row[1..-1] 
                graph[row[0]] = [] 
                topic_pages.to_a[i..-1].each do |row2| 
                        row2 = row2.flatten 
                        topic_pages_attributes2 = row2[1..-1] 
                        num_matching_attributes = (topic_pages_attributes2 & topic_pages_attributes).count 
                        if num_matching_attributes >= similarity or num_matching_attributes == topic_pages_attributes2.count or num_matching_attributes == topic_pages_attributes.count 
                                graph[row[0]].push(row2[0]) 
                        end 
                end 
                csv << [row[0], graph[row[0]]].flatten 
        end 
end 

请您参考如下方法:

  1. 基准。例如使用 Python 附带的 cProfile。在您的代码中很容易出现一些代价高昂的低效问题,而且它们很容易在密集型应用程序中以 10 倍的性能成本出现。

    漂亮的代码如

    (topic_pages_attributes2 & topic_pages_attributes).count 
    

    可能最终证明是您运行时的一个主要因素,可以通过使用更传统的代码轻松减少。

  2. 使用更高效的语言。例如在 benchmarksgame.alioth ,在许多密集型问题上,最快 Python 3 程序的平均速度比最快的 C 程序慢 63 倍(Ruby 为 67 倍,JRuby 为 33 倍)。是的,性能差距可能很大,即使使用优化良好的 Python 代码也是如此。但是如果你没有优化你的代码,它可能会更大;通过使用更高效的语言并仔细优化您的代码,您可能可以获得 100 到 1000 倍的加速。

  3. 考虑更巧妙地表述您的问题。例如,不是遍历每个节点,而是遍历每个一次。在你的情况下,这可能意味着建立一个倒排索引,主题 ->页面。这与文本搜索引擎的工作方式非常相似,也是在集群上计算此类操作的一种流行方式:可以在单独的节点上拆分各个主题。这种方法受益于数据的稀疏性。 这可以大大缩短算法的运行时间。

    您有大约 3 个 Mio 文档。从你的总数据量来看,他们平均大概只有不到100个topic吧?您的成对比较方法需要 3mio^2 比较,这会伤害您。如果更受欢迎的主题每个仅用于 30.000 个文档,则您可能只需计算 30k^2 * 主题数即可。假设您有 100 个非常受欢迎的主题(稀有主题无关紧要),这将是 100 倍的加速。

  4. 简化您的问题。例如,首先通过排序合并具有完全相同主题的所有文档。为了使这更有效,还要消除所有只出现一次的主题。但可能只有大约 10.000-100.000 个不同的集合文档。使用排序可以轻松解决此步骤,并将使您的问题简单 900-90000 倍(假设高于值范围)。

其中一些数字可能过于乐观 - 例如,根本没有考虑 IO,如果您的问题受 I/O 限制,使用 C/Java 可能帮不上什么忙。可能有一些非常流行的主题可能会损害 C 中讨论的方法。对于 D),您需要 O(n log n) 时间来对数据进行排序;但是对此有很好的实现。但这绝对是您应该做的简化。这些文档还将在您的最终数据中形成完全连接的派系,这也可能会影响其他分析。


评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!