Python Multiprocessing: ошибки из разных кодов - PullRequest
1 голос
/ 10 ноября 2019

У меня есть датафрейм с 10 миллионами строк. Это занимает слишком много времени для итерации и вычисления каждой строки. Я хотел бы получить результаты в более короткие сроки. Я пробовал разные многопроцессорные коды, но каждый раз сталкивался с разными ошибками. Может кто-то мне поможет по этому поводу. Заранее спасибо.

d3 - это фрейм данных с более чем 10 миллионами строк и 29 столбцами. Имя последнего столбца - «Расчет», все значения в этом столбце равны нулю. Используя значения других столбцов, я вычислил новые значения и установил новые значения для каждой строки столбца «Расчет».

Первый код

def fun():
   for i in d3.index:
        if (d3.iloc[i, 3:4])[0] == (d3.iloc[i + 1, 3:4])[0]:
            d3.loc[d3.index[i], 'Calculation']==(d3.iloc[i, 22:23] - d3.iloc[i + 1, 22:23])
        else:
            d3.loc[d3.index[i],'Calculation']=d3.iloc[i, 13:14][0]

if __name__=="__main__":
    p1 = mp.Process(target=fun, args=())
    p2 = mp.Process(target=fun, args=())
    p3 = mp.Process(target=fun, args=())
    p4 = mp.Process(target=fun, args=())
    p1.start()
    p2.start()
    p3.start()
    p4.start()

Второй код

def fun(i):
    if (d3.iloc[i, 3:4])[0] == (d3.iloc[i + 1, 3:4])[0]:
       d3.set_value(i, "Calculation", (d3.iloc[i, 22:23] - d3.iloc[i + 1, 22:23]))
    else:
       d3.set_value(i, "Calculation", d3.iloc[i, 13:14])

if __name__=="__main__":
    p1 = mp.Process(target=fun, args=(d3.index, ))
    p2 = mp.Process(target=fun, args=(d3.index, ))
    p3 = mp.Process(target=fun, args=(d3.index, ))
    p4 = mp.Process(target=fun, args=(d3.index, ))
    p1.start()
    p2.start()
    p3.start()
    p4.start()
    p1.join()
    p2.join()
    p3.join()
    p4.join()

Третий код

def fun(q):

    for i in d3.index:
        if (d3.iloc[i, 3:4])[0] == (d3.iloc[i + 1, 3:4])[0]:
           d3.loc[d3.index[i], 'Calculation']==(d3.iloc[i, 22:23] - d3.iloc[i + 1, 22:23])
        else:
            d3.loc[d3.index[i], 'Calculation']==(d3.iloc[i, 22:23] - d3.iloc[i + 1, 22:23])
    q.put(d3)``

if __name__ == "__main__":
    q = mp.Queue()
    processes = [mp.Process(target=fun, args=(q,)) for x in range(4)]
    for p in processes:
       p.start()
    for p in processes:
       p.join()
    results = [q.get() for p in processes]

Ошибка1:

File "pandas\_libs\ops.pyx", line 103, in pandas._libs.ops.vec_compare
ValueError: Buffer has wrong number of dimensions (expected 1, got 0)

Ошибка2:

File "pandas\_libs\hashtable_class_helper.pxi", line 1614, in     pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 0

Ошибка3:

File "pandas\_libs\ops.pyx", line 103, in pandas._libs.ops.vec_compare
ValueError: Buffer has wrong number of dimensions (expected 1, got 0)

1 Ответ

1 голос
/ 10 ноября 2019

В третьем примере вам нужно передать q и d3 вашим подпроцессам. Что происходит в сцене, так это то, что если fun (q, d3) изменяет d3, то d3 копируется в пространство памяти, выделенное для подпроцесса, который выполняется fun (q, d3) перед изменением. Если d3 не изменен в подпроцессе, подпроцесс сохраняет только ссылку на d3 из родительского процесса.

Теперь, если d3 очень велико, и вы хотите уменьшитьваше время выполнения и требования к памяти, я бы только передал ссылку на d3 вашим 4 подпроцессам (т.е. просто не изменяйте d3 в ваших подпроцессах, чтобы избежать копирования) вместе с индексом строки начала и остановки. Тогда fun (d3, q, start_idx, stop_idx) просто вернет список длины stop_idx - start_idx , который ваш родительский процесс позже поместит обратно в исходный столбец d3 с именем Расчет .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...