程序运行太慢!:建议算法/实现优化



我有一个巨大的python列表(A)。名单A的长度约为90,000。每个内部列表包含大约 700 个元组(datetime.date,string)。现在,我正在分析这些数据。我正在做的是我在内部列表中取一个大小为 x 的窗口,其中 - x = len(inner list) * (some fraction <= 1) 并且我正在保存每个有序对 (a,b),其中 a 出现在该窗口中的 b 之前(实际上内部列表是排序的 wrt 时间)。我正在将此窗口移动到最后一个元素,一次从一端添加一个元素,并从另一端删除O(window-size)这需要时间,因为我只考虑新的元组。我的代码:

for i in xrange(window_size):
        j = i+1;
        while j<window_size:
            check_and_update(cur, my_list[i][1], my_list[j][1],log);
            j=j+1
    i=1;
    while i<=len(my_list)-window_size: 
        j=i;
        k=i+window_size-1;
        while j<k:
            check_and_update(cur, my_list[j][1], my_list[k][1],log);  
            j+=1
        i += 1  

这里cur实际上是一个sqlite3数据库游标,my_list是一个包含元组的列表,我为A中的所有列表迭代此代码,log是一个打开的日志文件。在方法 check_and_update() 中,我正在查找我的数据库以查找元组(如果存在),否则我插入它,以及到目前为止出现的总数。法典:

def check_and_update(cur,start,end,log):    
    t = str(start)+":"+ str(end)
    cur.execute("INSERT OR REPLACE INTO Extra (tuple,count)
                 VALUES ( ? , coalesce((SELECT count +1 from Extra WHERE tuple = ?),1))",[t,t])

正如预期的那样,这个元组的数量是巨大的,我之前已经尝试过字典,它很快就会消耗内存。所以,我求助于SQLite3,但现在它太慢了。我尝试过索引,但没有帮助。可能我的程序花费了很多时间来查询和更新数据库。您对此问题有什么优化想法吗?可能会更改算法或一些不同的方法/工具。谢谢!

编辑:我的目标是找到窗口中出现的字符串元组总数,按它们出现的不同内部列表的数量分组。我使用此查询提取此信息:

for i in range(1,size+1):       
        cur.execute('select * from Extra where count = ?',str(i))
        #other stuff

例如(我忽略日期条目并将它们写为"dt"):

My_list = [
            [ ( dt,'user1') , (dt, 'user2'), (dt, 'user3') ]
            [ ( dt,'user3') , (dt, 'user4')]
            [ ( dt,'user2') , (dt, 'user3'), (dt,'user1') ]
          ]

在这里,如果我取分数 = 1,则结果:

only 1 occurrence in window: 5 (user 1-2,1-3,3-4,2-1,3-1)
only 2 occurrence in window: 2 (user 2-3)

让我直截了当。

您最多有大约 220 亿个潜在元组(对于 90000 个列表,700 个中的任何一个,以下任何条目,平均 350 个),根据窗口大小,这些元组可能会更少。 你想找到,但是它们出现在内部列表中的数量,有多少元组。

此大小的数据必须驻留在磁盘上。 由于大小而存在于磁盘上的数据的规则是,"切勿随机访问,而是生成然后排序。

所以我建议你把每个元组写到一个日志文件中,每行一个元组。 对该文件进行排序。 现在,任何给定元组的所有实例都位于一个位置。 然后运行该文件,并为每个元组发出它出现的次数(即它在其中的内部列表数)。 对第二个文件进行排序。 现在运行该文件,您可以提取 1x、2x、3x 等出现的元组数量。

如果您有多台机器,则很容易将其转换为MapReduce。 (这在道德上是相同的方法,但你可以并行化很多东西。

Apache Hadoop是适合此类问题的MapReduce实现之一:

最新更新