Многопоточное приложение Python медленнее однопоточной реализации

Я написал эту программу, чтобы правильно научиться использовать многопоточность. Я хочу реализовать что-то подобное в своей собственной программе:

import numpy as np
import time
import os
import math
import random

from threading import Thread

def powExp(x, r):
    for c in range(x.shape[1]):
        x[r][c] = math.pow(100, x[r][c])

def main():
    print()
    rows = 100
    cols = 100

    x = np.random.random((rows, cols))
    y = x.copy()


    start = time.time()

    threads = []
    for r in range(x.shape[0]):
        t = Thread(target = powExp, args = (x, r))
        threads.append(t)
        t.start()
    for t in threads:
        t.join()

    end = time.time()

    print("Multithreaded calculation took {n} seconds!".format(n = end - start))

    start = time.time()

    for r in range(y.shape[0]):
        for c in range(y.shape[1]):
            y[r][c] = math.pow(100, y[r][c])

    end = time.time()

    print("Singlethreaded calculation took {n} seconds!".format(n = end - start))
    print()

    randRow = random.randint(0, rows - 1)
    randCol = random.randint(0, cols - 1)

    print("Checking random indices in x and y:")
    print("x[{rR}][{rC}]: = {n}".format(rR = randRow, rC = randCol, n = x[randRow][randCol]))
    print("y[{rR}][{rC}]: = {n}".format(rR = randRow, rC = randCol, n = y[randRow][randCol]))
    print()

    for r in range(x.shape[0]):
        for c in range(x.shape[1]):
            if(x[r][c] != y[r][c]):
                print("ERROR NO WORK WAS DONE")
                print("x[{r}][{c}]: {n} == y[{r}][{c}]: {ny}".format(
                        r = r,
                        c = c,
                        n = x[r][c],
                        ny = y[r][c]
                    ))
                quit()

    assert(np.array_equal(x, y))

if __name__ == main():
    main()

Как видно из кода, цель здесь — распараллелить операцию math.pow(100, x[r][c]), создав поток для каждого столбца. Однако этот код очень медленный, намного медленнее, чем однопоточные версии.

Вывод:

Multithreaded calculation took 0.026447772979736328 seconds!
Singlethreaded calculation took 0.006798267364501953 seconds!

Checking random indices in x and y:
x[58][58]: = 9.792315687115973
y[58][58]: = 9.792315687115973

Я искал через stackoverflow и нашел некоторую информацию о том, что GIL заставляет байт-код python выполняться только на одном ядре. Однако я не уверен, что именно это ограничивает мою распараллеливание. Я попытался перестроить параллельный цикл for, используя пулы вместо потоков. Кажется, ничего не работает.

Производительность кода Python снижается при многопоточности

EDIT: В этой теме обсуждается та же проблема. Неужели из-за GIL совсем нельзя повысить производительность с помощью многопоточности в python? Является ли GIL причиной моих замедлений?

EDIT 2 (2017-01-18): Итак, из того, что я смог собрать после небольшого поиска в Интернете, кажется, что python действительно плохо подходит для параллелизма. То, что я пытаюсь сделать, это распараллелить функцию python, используемую в нейронной сети, реализованной в тензорном потоке... кажется, что добавление пользовательской операции - это путь.


person LiquidFunk    schedule 16.01.2017    source источник
comment
Возможный дубликат снижения производительности кода Python при многопоточности   -  person Tagc    schedule 16.01.2017
comment
Вы знаете, что запускаете 10 000 потоков?   -  person Klaus D.    schedule 16.01.2017
comment
@Клаус Д. Извините, я пропустил это. Я обновил код и вывод. Все еще есть та же проблема, несмотря на то, что не было запущено такое нелепое количество потоков!   -  person LiquidFunk    schedule 16.01.2017
comment
Да, GIL испортит вашу производительность. Не можете ли вы изменить свой код, чтобы использовать многопроцессорность?   -  person yorodm    schedule 16.01.2017


Ответы (1)


Количество вопросов здесь довольно... много. Слишком много (системных!) потоков, которые выполняют слишком мало работы, GIL и т. д. Это то, что я считаю действительно хорошим введением в параллелизм в Python:

https://www.youtube.com/watch?v=MCs5OvhV9S4

Живое кодирование — это круто.

person Dervin Thunk    schedule 16.01.2017
comment
Я обновил код и вывод за несколько минут до того, как вы опубликовали. Безумное количество тем было удалено! Хотя ссылку посмотрю, спасибо. - person LiquidFunk; 16.01.2017