使用python应用程序进行多处理以缩短当前36小时的运行时间

使用python应用程序进行多处理以缩短当前36小时的运行时间,python,multiprocess,Python,Multiprocess,我目前正在从事一个数据挖掘项目,该项目正在创建一个18000x18000的相似性矩阵 以下是构建矩阵的两种方法 def CreateSimilarityMatrix(dbSubsetData, distancePairsList): global matrix matrix = [ [0.0 for y in range(dbSubsetData.shape[0])] for x in range(dbSubsetData.shape[0])] for i in ran

我目前正在从事一个数据挖掘项目,该项目正在创建一个18000x18000的相似性矩阵

以下是构建矩阵的两种方法

def CreateSimilarityMatrix(dbSubsetData, distancePairsList):

    global matrix
    matrix = [ [0.0 for y in range(dbSubsetData.shape[0])] for x in range(dbSubsetData.shape[0])]
    for i in range(len(dbSubsetData)): #record1

        SimilarityArray = []
        start = time.time()
        for j in range(i+1, len(dbSubsetData)): #record2
            Similarity = GetDistanceBetweenTwoRecords(dbSubsetData, i, j, distancePairsList)

            #The similarities are all very small numbers which might be why the preference value needs to be so precise. 
            #Let's multiply the value by a scalar 10 to give the values more range. 
            matrix[i][j] = Similarity * 10.0
            matrix[j][i] = Similarity * 10.0

        end = time.time()
    return matrix

def GetDistanceBetweenTwoRecords(dbSubsetData, i, j, distancePairsList):

    Record1 = dbSubsetData.iloc[i]
    Record2 = dbSubsetData.iloc[j]
    columns = dbSubsetData.columns
    distancer    = 0.0
    distancec    = 0.0

    for i in range(len(Record1)):

        columnName = columns[i]
        Record1Value = Record1[i]
        Record2Value = Record2[i]

        if(Record1Value != Record2Value):
            ob = distancePairsList[distancePairsDict[columnName]-1]

            if(ob.attributeType == "String"):
                strValue = Record1Value+":"+Record2Value
                strValue2 = Record2Value+":"+Record1Value

                if strValue in ob.distancePairs:
                    val = ((ob.distancePairs[strValue])**2) 
                    val = val * -1
                    distancec = distancec + val
                elif strValue2 in ob.distancePairs:
                    val = ((ob.distancePairs[strValue2])**2)
                    val = val * -1
                    distancec = distancec + val

            elif(ob.attributeType == "Number"):
                val = ((Record1Value - Record2Value)*ob.getSignificance())**2 
                val = val * -1
                distancer = distancer + val

    distance = distancer + distancec
    return distance
每个迭代循环18000x19次(每行18000次,每个属性19次)。迭代的总数是(18000x18000x19)/2,因为它是对称的,因此我只需要做矩阵的一半。这将需要大约36个小时才能完成,这显然是我想要缩短的时间

我认为多重处理就是诀窍。由于每一行都独立地生成数字并将其拟合到矩阵中,因此我可以使用CreateSimilarityMatrix运行多进程。所以我在函数中创建了它,它将创建我的进程

matrix = [ [0.0 for y in range(SubsetDBNormalizedAttributes.shape[0])] for x in range(SubsetDBNormalizedAttributes.shape[0])] 
if __name__ == '__main__':    
    procs = []
    for i in range(4):
        proc = Process(target=CreateSimilarityMatrix, args=(SubsetDBNormalizedAttributes, distancePairsList, i, 4))
        procs.append(proc)
        proc.start()
        proc.join()
CreateSimilarityMatrix现在更改为

def CreateSimilarityMatrix(dbSubsetData, distancePairsList, counter=0, iteration=1):

    global Matrix

    for i in range(counter, len(dbSubsetData), iteration): #record1

        SimilarityArray = []
        start = time.time()
        for j in range(i+1, len(dbSubsetData)): #record2
            Similarity = GetDistanceBetweenTwoRecords(dbSubsetData, i, j, distancePairsList)
            #print("Similarity Between Records",i,":",j," is ", Similarity)

            #The similarities are all very small numbers which might be why the preference value needs to be so precise. 
            #Let's multiply the value by a scalar 10 to give the values more range. 
            Matrix[i][j] = Similarity * 10.0
            Matrix[j][i] = Similarity * 10.0

        end = time.time()
        print("Iteration",i,"took",end-start,"(s)")

目前这是s-l-o-w。真的很慢。启动一个进程需要几分钟,然后启动下一个进程需要几分钟。我以为这些应该同时运行?我对流程的应用是否不正确

如果您使用的是CPython,则有一种称为全局解释器锁(global interprelator lock,GIL)的方法,这使得在加快速度的同时很难实现多线程,反而会大大降低速度


如果要处理矩阵,请使用numpy,它肯定比普通Python快得多。

什么是
getDistanceBetweenWorneCords
?使用标准的NumPy优化技术一次重写整个NumPy阵列,可能比并行处理带来更大的经济效益。由于Python的开销,您损失的时间比您想象的要多。您是否尝试过使用NumPy,因为Python处理矩阵的速度非常慢。您应该阅读此()并试一试。@FernandoMarques:Not
numpy.matrix
。认真对待“不再建议使用此类”的大警告。常规的NumPy数组是一个不错的选择。实际上,让我问一个澄清的问题。变量矩阵是一个常规python数组,但dbSubsetData是一个数组。你是说矩阵阵列本身吗?对矩阵使用numpy?GetDistanceBetweenTwoRecords获取dbSubsetData、i和j以及对象距离对列表。我从dbSubsetData获取记录I和j。我要做的是遍历每一列,得到[rowi][column]和[rowj][column]之间的距离。距离值位于我的距离值对中,这是一个对象数组。每个对象包含每个潜在列值的对距离。因此,每个属性有一个对象和多个可能的距离对。如果有一种方法可以一次性完成同一行中所有列的所有操作,那么肯定会加快速度。这是正确的。GIL使多线程对于CPU密集型线程毫无意义,OP应该使用多处理。我实际上使用的是多处理。我错误地说我使用了多线程。我使用的库和例程是本页提供的一种多处理方法。我已经编辑了这一页,让它更清晰。谢谢你的更正,我应该删除我的答案吗?(我对这个网站有点陌生)我实际上在使用你和其他人关于numpy的指导,所以部分答案肯定仍然有效。这就是解决方案!也就是说,不必担心多重处理。如果您要构建和读取一个拥有100000条记录的数据库,请使用Numpy!不要使用Pandas或python数组。谢谢你的提示。现在,每次迭代所用的时间不到一秒钟。花了36个小时的时间现在大约需要90分钟。真是太激烈了。