Многопроцессорная обработка Python с использованием multiprocessing.pool не использует 100% CPU - PullRequest
0 голосов
/ 26 апреля 2018

Я хочу зашифровать список из 300 чисел, используя гомоморфное (paillier) шифрование. Это занимает примерно 3000 мс на моем ноутбуке, намного больше на моем малиновом пи. Я хотел бы ускорить это, поэтому я попытался использовать многопоточность:

from multiprocessing.dummy import pool as ThreadPool

def test_1_performance_of_encryption(self):

    print("Test: Blind encryption performance test")
    print("-----------------------------")
    print()
    # Only blinds are encrypted
    for y in range(0, ((NUMBER_OF_RUNS//SENSOR_SAMPLES_PER_BLIND)*NUM_OF_DATA_PROCESSORS)):
        print("Round {}:".format(y+1))
        print("Encrypting {} blinds...".format(NUM_OF_SENSOR_SAMPLES))
        encrypted_blinds.clear()
        millis_start = int(round(time.time() * 1000))

        for x in range(0, NUM_OF_SENSOR_SAMPLES):
            encrypted_blinds.append(public_keys[0].encrypt(blinds[x]))

        millis_end = int(round(time.time() * 1000))
        time_elapsed_enc.append(millis_end - millis_start)
        print("Time elapsed: {}ms".format(time_elapsed_enc[y]))

    print("Test finished. Time elapsed:")
    print("Min: {} | Max: {} | Avg: {}".format(min(time_elapsed_enc), max(time_elapsed_enc),
                                               (sum(time_elapsed_enc)/len(time_elapsed_enc))))
    print()

@profile
def test_1a_performance_of_encryption_multithreaded(self):

    print("Test: Blind encryption performance test with {} threads".format(NUM_OF_THREADS))
    for y in range(0, ((NUMBER_OF_RUNS//SENSOR_SAMPLES_PER_BLIND)*NUM_OF_DATA_PROCESSORS)):
        print("Round {}:".format(y+1))
        print("Encrypting {} blinds...".format(len(blinds)))
        millis_start = int(round(time.time() * 1000))

        encrypted_blinds_multithreaded = pool.map(public_keys[0].encrypt, blinds)

        millis_end = int(round(time.time() * 1000))
        time_elapsed_enc_multithread.append(millis_end - millis_start)
        print("Time elapsed: {}ms".format(time_elapsed_enc_multithread[y]))

    print("Test finished. Time elapsed:")
    print("Min: {} | Max: {} | Avg: {}".format(min(time_elapsed_enc_multithread), max(time_elapsed_enc_multithread),
                                               (sum(time_elapsed_enc_multithread) / len(time_elapsed_enc_multithread))))
    print()

Однако оба теста заканчиваются примерно в одно и то же время. В то время как однопоточный метод использует одно ядро ​​на 100%, многопоточная версия использует их все, но все равно создает нагрузку, равную 1 (равно 1 ядру на 100%). Я что-то здесь не так делаю? Я прочитал этот вопрос, и он отвечает: Python multiprocessing.Pool () не использует 100% каждого процессора , однако я не верю, что причина здесь в межпроцессном взаимодействии, поскольку это было бы очень странно что он устанавливается точно при нагрузке 1 ...

EDIT : я использовал multiprocessing.dummy вместо multiprocessing. Я думаю, что здесь использовались несколько потоков вместо процессов, и несколько потоков не могут выполняться параллельно в Python из-за того, что называется GIL (глобальная блокировка интерпретатора). Я исправил это, изменив multiprocessing.dummy на multiprocessing. У меня сейчас n процессов и загрузка процессора 100%.

...