Многопроцессорная обработка с приложением Python для сокращения времени работы, которое в настоящее время составляет 36 часов - PullRequest
0 голосов
/ 15 февраля 2019

В настоящее время я работаю над проектом интеллектуального анализа данных, который создает матрицу подобия, которая составляет 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 часов, и это тот период времени, который я, очевидно, хочу побриться.

Я подумал, что многопроцессорная обработка - это хитрость.Поскольку каждая строка независимо генерирует числа и подгоняет их к матрице, я мог бы запустить многопроцессорную работу с CreateSdentifityMatrix.Таким образом, я создал это в функции, которая будет создавать мои процессы

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()

CreateSdentifityMatrix теперь изменен на

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)")

В настоящее время это идет медленно.Это действительно медленно.Для запуска одного процесса требуются минуты, а для запуска следующего - минуты.Я думал, что они должны были работать одновременно?Мое приложение процесса неверно?

1 Ответ

0 голосов
/ 15 февраля 2019

Если вы используете CPython, есть нечто, называемое глобальной блокировкой интерпретатора (GIL), которое затрудняет на самом деле многопоточность при одновременном ускорении и может существенно замедлить его.

Если вы имеете делос матрицами используйте numpy, который определенно намного быстрее, чем обычный Python.

...