Я бы ожидал некоторых накладных расходов из-за переключения контекста при запуске двух процессов на одном ядре ЦП. Чего я не ожидал, так это больших накладных расходов при запуске двух процессов на двух отдельных ядрах ЦП.
Вот моя программа на Python для подсчета:
import time
start = time.time()
j = 0
for i in range(0, 80000000):
j += i
elapsed = time.time() - start
print("\nElapsed: %f" % elapsed)
Сама по себе эта программа завершается примерно за 7 секунд. Если я запускаю эту программу дважды одновременно на одном и том же ядре ЦП:
$ taskset --cpu-list 0 time python3 cpu-bound.py & taskset --cpu-list 0 time python3 cpu-bound.py &
Elapsed: 15.553317
7.77user 0.01system 0:15.59elapsed 49%CPU (0avgtext+0avgdata 8924maxresident)k
0inputs+0outputs (0major+942minor)pagefaults 0swaps
Elapsed: 15.840124
8.10user 0.00system 0:15.90elapsed 50%CPU (0avgtext+0avgdata 9060maxresident)k
0inputs+0outputs (0major+946minor)pagefaults 0swaps
Я получаю 14-15 секунд, что ожидается, поскольку они работают на одном и том же ЦП, поэтому один должен быть приостановлен для запуска другого и т. д. Однако запуск двух процессов на разных ядрах ЦП:
$ taskset --cpu-list 0 time python3 cpu-bound.py & taskset --cpu-list 1 time python3 cpu-bound.py &
Elapsed: 17.081092
17.10user 0.00system 0:17.12elapsed 99%CPU (0avgtext+0avgdata 8848maxresident)k
0inputs+0outputs (0major+943minor)pagefaults 0swaps
Elapsed: 17.094898
17.10user 0.00system 0:17.14elapsed 99%CPU (0avgtext+0avgdata 8948maxresident)k
0inputs+0outputs (0major+944minor)pagefaults 0swaps
Я ожидаю, что каждый процесс сообщит время, близкое к исходным 7 секундам, потому что процессы выполняются параллельно и на отдельных ядрах.
Тем не менее, я вижу 15-17 секунд выполнения каждого процесса.
Может ли кто-нибудь пролить свет на это поведение? Спасибо!
Обновлять: Ниже я опишу среды, в которых я пытался это запустить.
Сначала я запустил это в контейнере Docker на Mac M1 с 4 ядрами. CPU 0 и 1 — это первое и второе ядро соответственно. Затем я снова запустил виртуальную машину t3.medium на AWS с двумя виртуальными ЦП и получил аналогичные результаты.
Обновлять: Я также получил аналогичные результаты в PHP, а также статический пул php-fpm с 1 воркером (для последовательного запуска), с 2 воркерами с привязкой к ЦП (для параллельной работы на одном ядре) и с 2 воркерами без привязки (параллельный на двух ядрах). Я наблюдал похожее поведение — параллельный запуск на отдельных ядрах далеко не так быстр, как исходный одиночный запуск.
Затем я решил попробовать аналогичную программу на C, и результаты были совсем другими и очень соответствовали тому, что я ожидал в первую очередь:
#include <stdio.h>
#include <time.h>
int main() {
time_t t;
double elapsed;
int i, j = 0;
t = time(NULL);
for (i = 0; i <= 2000000000; i++) {
j += i;
}
t = time(NULL) - t;
elapsed = ((double) t);
printf("Elapsed: %f\n", elapsed);
return 0;
}
Один запуск длился около 6 секунд (время_t округляется до секунд):
$ ./a.out
Elapsed: 6.000000
Два запуска на одном ядре ЦП дали:
$ taskset --cpu-list 0 ./a.out & taskset --cpu-list 0 ./a.out &
Elapsed: 12.00
Elapsed: 12.00
Два прогона на отдельных ядрах ЦП дали:
$ taskset --cpu-list 0 ./a.out & taskset --cpu-list 1 ./a.out &
Elapsed: 6.00
Elapsed: 6.00
Такое поведение больше соответствует тому, что я ожидал изначально, но почему оно так сильно отличается для Python и PHP?
1 ответ
Такое поведение больше соответствует тому, что я ожидал изначально, но почему оно так сильно отличается для Python и PHP?
И Python, и PHP являются интерпретируемыми языками высокого уровня. Вы не можете точно знать, что интерпретатор делает с вашим кодом.
Затем я решил попробовать аналогичную программу на C, и результаты были совсем другими и очень соответствовали тому, что я ожидал в первую очередь.
Это одна из основных причин использования C.
Сначала я запустил это в контейнере Docker на Mac M1 с 4 ядрами. CPU 0 и 1 — это первое и второе ядро соответственно. Затем я снова запустил виртуальную машину t3.medium на AWS с двумя виртуальными ЦП и получил аналогичные результаты.
Также обратите внимание, что запускать такие тесты на виртуальных машинах или в контейнерах особого смысла нет.
Массимо
