Объяснение времени карты памяти в python при использовании нескольких процессов

Я использую 36-ядерный узел HPC. Спецификация заключается в том, что узел имеет 2 процессора Intel Xeon E5-2695 v4 с 18 ядрами каждый. Я пытаюсь записать карту памяти из основного процесса, а подпроцесс считывает карту памяти и обновляет ее. Подпроцесс некоторое время спит перед обновлением. Я запускаю несколько подпроцессов параллельно.

Я проводил некоторое тестирование производительности и столкнулся со сценарием, который я объяснил ниже в результатах своего кода.

import time
from mmap import mmap
from multiprocessing import Process, Lock

f = open("results.csv", "w")
f.write("mmap_time,total_time\n")

def sub_process(m, mutex):
        while True:
                mutex.acquire()
                if m[0] == 72:                                  # equivalent to H
                        time.sleep(0.001)                       # sleep for 1 millisecond
                        m.seek(0)
                        m.write(bytes("child", "utf-8"))
                mutex.release()
                time.sleep(0.00001)

n = 80                                                          #Num of Subprocess

m = []
mutex = []
process = []
for i in range(n):
        m.append(mmap(-1, 5))
        mutex.append(Lock())
        process.append(Process(target = sub_process, args = (m[i], mutex[i])))
        process[i].start()

for it in range(100):
        total_start_time = time.time_ns() / (10 ** 6)           # milliseconds time
        mmap_dict = {}
        for i in range(n):
                mmap_dict[m[i]] = mutex[i]
        for mmap,mu in mmap_dict.items():
                mu.acquire()
                mmap.seek(0)
                mmap.write(bytes("Hello", "utf-8"))
                mu.release()
        condition = True
        mmap_start_time = time.time_ns() / (10 ** 6)
        while condition:
                l = []                                          # list to hold the mmap that were updated
                for mmap,mu in mmap_dict.items():
                        mu.acquire()
                        mmap.seek(0)
                        if mmap[0] == 99:                       # equivalent to c
                                l.append(mmap)
                        mu.release()
                for mmap in l:del mmap_dict[mmap]
                if len(mmap_dict) == 0:
                        del mmap_dict
                        condition = False
        mmap_end_time = time.time_ns() / (10 ** 6)
        total_end_time = time.time_ns() / (10 ** 6)
        f.write(str(mmap_end_time - mmap_start_time) + "," + str(total_end_time - total_start_time) + "\n")
f.close()
for i in range(n):
        process[i].terminate()
        m[i].close()

В каждом подпроцессе, когда он обнаруживает, что его карта памяти обновляется. Подпроцесс спит в течение 1 миллисекунды, а затем обновляет карту памяти.

Выходные данные были следующими (все значения времени являются средними значениями 100 итераций и указаны в миллисекундах):

|---------------------|-----------------|-----------------|
|    Num_Subprocess   |    mmap_time    |    total_time   |
|---------------------|-----------------|-----------------|
|          1          |   1.122416992   |    1.126069336  |
|---------------------|-----------------|-----------------|
|         10          |   1.115305176   |    1.130327148  |
|---------------------|-----------------|-----------------|
|         40          |   1.133754883   |    1.212219238  |
|---------------------|-----------------|-----------------|
|         80          |   1.172145996   |    1.350251465  |
|---------------------|-----------------|-----------------|

Я понимаю, что время mmap находится в диапазоне 1,1, потому что я записываю только время, необходимое для того, чтобы основной процесс увидел отражение. Но для 40 подпроцессов я ожидаю, что общее время составит не менее 2 миллисекунд, так как я сплю 1 миллисекунду в подпроцессе, а у меня всего 36 ядер, а для 80 подпроцессов я ожидаю не менее 3 миллисекунд. Может кто-нибудь объяснить, почему общее время ниже ожидаемого значения? Есть ли ошибка в моем коде?


person Manoj    schedule 03.09.2019    source источник


Ответы (1)


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

Вместо сна я попытался добавить некоторые случайные вычисления в подчиненные рабочие процессы, которые занимают примерно 1 миллисекунду. Я скамейке отметил расчеты на моей машине.

def sub_process(m, mutex):
        while True:
                mutex.acquire()
                if m[0] == 72:
                        for i in range(1000):
                                result = math.pow(math.sqrt(math.cos(math.sin(i*math.pi))),2)
                        m.seek(0)
                        m.write(bytes("child", "utf-8"))
                mutex.release()
                time.sleep(0.00001)

Теперь мои результаты были

|---------------------|-----------------|-----------------|
|    Num_Subprocess   |    mmap_time    |    total_time   |
|---------------------|-----------------|-----------------|
|          1          |     1.00910     |     1.01289     |
|---------------------|-----------------|-----------------|
|         10          |     6.29030     |     6.30628     |
|---------------------|-----------------|-----------------|
|         40          |     19.72357    |     19.78807    |
|---------------------|-----------------|-----------------|
|         80          |     51.22329    |     51.33896    |
|---------------------|-----------------|-----------------|

Хотя время сейчас кажется высоким. Результаты были гораздо более реалистичными и приемлемыми.

person Manoj    schedule 06.09.2019