Tengo un script de Python simple que lee desde stdin (una sola línea), realiza algún procesamiento (análisis de cadenas, sin IO involucrado) y lo envía a stdout
e.g. python parse.py < in.txt > out.txt
Tengo un in.txt
tamaño de alrededor de 200 GB y uso paralelo para acelerarlo (tengo 8 núcleos de CPU).
cat in.txt | parallel -j8 -N1 --pipe python parse.py
Lo que observé que la CPU no se está utilizando por completo, por ejemplo
%Cpu0 : 9.1 us, 22.7 sy, 0.0 ni, 68.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 27.3 us, 13.6 sy, 0.0 ni, 59.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 14.3 us, 71.4 sy, 0.0 ni, 14.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 14.3 us, 28.6 sy, 0.0 ni, 57.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu4 : 14.3 us, 38.1 sy, 0.0 ni, 47.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu5 : 4.8 us, 23.8 sy, 0.0 ni, 71.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu6 : 15.0 us, 20.0 sy, 0.0 ni, 65.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu7 : 23.8 us, 19.0 sy, 0.0 ni, 57.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
Y
ps ax | grep python
Obtuve
12450 ? S 0:00 /bin/bash -c sh -c 'dd bs=1 count=1 of=/tmp/2NQLo8j4qy.chr 2>/dev/null'; test ! -s "/tmp/2NQLo8j4qy.chr" && rm -f "/tmp/2NQLo8j4qy.chr" && exec true; (cat /tmp/2NQLo8j4qy.chr; rm /tmp/2NQLo8j4qy.chr; cat - ) | (python parse.py);
12453 ? S 0:00 /bin/bash -c sh -c 'dd bs=1 count=1 of=/tmp/zYnfr4Ss8H.chr 2>/dev/null'; test ! -s "/tmp/zYnfr4Ss8H.chr" && rm -f "/tmp/zYnfr4Ss8H.chr" && exec true; (cat /tmp/zYnfr4Ss8H.chr; rm /tmp/zYnfr4Ss8H.chr; cat - ) | (python parse.py);
12456 ? S 0:00 /bin/bash -c sh -c 'dd bs=1 count=1 of=/tmp/wlrI14juYz.chr 2>/dev/null'; test ! -s "/tmp/wlrI14juYz.chr" && rm -f "/tmp/wlrI14juYz.chr" && exec true; (cat /tmp/wlrI14juYz.chr; rm /tmp/wlrI14juYz.chr; cat - ) | (python parse.py);
12459 ? S 0:00 /bin/bash -c sh -c 'dd bs=1 count=1 of=/tmp/cyArLNBTTm.chr 2>/dev/null'; test ! -s "/tmp/cyArLNBTTm.chr" && rm -f "/tmp/cyArLNBTTm.chr" && exec true; (cat /tmp/cyArLNBTTm.chr; rm /tmp/cyArLNBTTm.chr; cat - ) | (python parse.py);
12461 pts/0 S+ 0:00 grep --color=auto python
15211 ? S 144:22 perl /usr/bin/parallel -j8 -N1 --pipe python parse.py
Cada vez que ejecuto ps ax | grep python
obtengo diferentes archivos temporales, ¿supongo que se desperdicia CPU al tratar con estos archivos temporales? ¿O estoy haciendo algo mal?
Respuesta1
Si bien la respuesta de Mark es correcta y totalmente compatible, es posible que desee probar una nueva función.
cat file | parallel --pipe ...
alcanza un máximo de alrededor de 100 MB/s.
La nueva opción experimental --pipepart ofrece > 2 GB/s, pero requiere que in.txt sea un archivo real (buscable):
parallel -a in.txt --block 100M --pipepart python parse.py
Respuesta2
Esto -N1
está provocando que se cree un proceso por línea. Estás viendo la sobrecarga de la configuración paralela. Debe modificar la secuencia de comandos de Python para manejar más de una línea. Entonces cat in.txt | parallel --pipe python parse.py
debería hacer un uso completo de las CPU.