Пожалуйста, не используйте кавычки для акцента. Они предназначены для разметки цитат, а не для подсвечивания произвольных блоков текста или привлечения внимания к вашим заголовкам. Мы уже обсуждали это раньше, есть объективно правильные и неправильные способы использования некоторых инструментов форматирования, которые предоставляет этот сайт, таких как кавычки. Как правило, вы можете свободно форматировать свои сообщения по своему усмотрению, но если кто-то исправит проблему, когда вы неправильно пометили свое сообщение, вы должны оставить свои правки в покое.

аюсь реализовать многопроцессорность в Python (Windows Server 2012) и испытываю трудности с достижением ожидаемого уровня повышения производительности. В частности, для ряда задач, которые почти полностью независимы,Я ожидаю линейного улучшения с дополнительными ядрами.

Я понимаю, что - особенно в Windows - есть издержки, связанные с открытием новых процессов[1]и что многие причуды базового кода могут помешать чистой тенденции. Но в теории тенденция в конечном итоге должна быть близкой к линейной для полностью распараллеленной задачи[2]; или, возможно, логистика, если я имел дело с частично последовательной задачей[3].

Однако, когда я запускаю multiprocessing.Pool для тестовой функции простой проверки (код ниже), я получаю почти идеальное отношение квадратного корня доN_cores=36 (количество физических ядер на моем сервере), прежде чем ожидаемая производительность достигнет, когда я войду в дополнительные логические ядра.

Вот график результатов моего теста производительности:
("Нормализованная производительность" является[ время выполнения с1 CPU-ядра] деленное на[ время выполнения сN CPU-ядра] ).

Нормально ли это резкое уменьшение отдачи при многопроцессорной обработке? Или я что-то упустил в своей реализации?

import numpy as np
from multiprocessing import Pool, cpu_count, Manager
import math as m
from functools import partial
from time import time

def check_prime(num):

    #Assert positive integer value
    if num!=m.floor(num) or num<1:
        print("Input must be a positive integer")
        return None

    #Check divisibility for all possible factors
    prime = True
    for i in range(2,num):
        if num%i==0: prime=False
    return prime

def cp_worker(num, L):
    prime = check_prime(num)
    L.append((num, prime))


def mp_primes(omag, mp=cpu_count()):
    with Manager() as manager:
        np.random.seed(0)
        numlist = np.random.randint(10**omag, 10**(omag+1), 100)

        L = manager.list()
        cp_worker_ptl = partial(cp_worker, L=L)

        try:
            pool = Pool(processes=mp)   
            list(pool.imap(cp_worker_ptl, numlist))
        except Exception as e:
            print(e)
        finally:
            pool.close() # no more tasks
            pool.join()

        return L


if __name__ == '__main__':
    rt = []
    for i in range(cpu_count()):
        t0 = time()
        mp_result = mp_primes(6, mp=i+1)
        t1 = time()
        rt.append(t1-t0)
        print("Using %i core(s), run time is %.2fs" % (i+1, rt[-1]))

Примечание: Я знаю, что для этой задачи было бы более эффективно реализоватьнарезания резьбы, но фактический скрипт, для которого этот является упрощенным аналогом, несовместим с многопоточностью Python из-за GIL.

Ответы на вопрос(1)

Ваш ответ на вопрос