Параллельные многопроцессные и многонитиевые программы Linux

Как указывалось ранее, параллельные программы зачастую используют процессы для выполнения отдельных ветвей. В эту категорию часто попадают программы сетевых служб, например сервер баз данных W:[PostgreSQL], служба удаленного доступа W:[SSH] и подобные.

Листинг ниже иллюстрирует программу postgres, выполняющуюся в шести параллельных процессах, один из которых — диспетчер, четыре служебных и еще один вызван подключением пользователя fitz к одноименной базе данных fitz.

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

Параллельные многопроцессные сервисы

fitz@ubuntu:~$ ps f -С postgres

PID    TTY                 STAT            TIME    COMMAND

1427   ?                       S                   0:01       /usr/lib/postgresql/9.1/bin/postgres -D …

1984  ?                       Ss                  0:25       \_ postgres: writer process

| 1985   ?                       Ss                 0:22       \_ postgres: wal writer process

| 1986   ?                       Ss                 0:05       \_ postgres: autovacuum launcher process

| 1987   ?                       Ss                 0:04       \_ postgres: stats collector process

21619   ?                       Ss                 0:00       \_ postgres: fitz   fitz [local] idle

fitz@ubuntu:~$ ssh ubuntu

fitz@ubuntu’s password:

Last login: Sat Nov 21 13:29:33 2015 from localhost

fitz@ubuntu:~$ ps f -C sshd

PID      TTY                    STAT           TIME        COMMAND

655       ?                          Ss                 0:00         /usr/sbin/sshd -D

21975  ?                          Ss                 0:00         \_ sshd: fitz [priv]

22086 ?                          S                   0:00         \_ sshd: fitz@pts/1

fitz@ubuntu:~$ ^Dвыход

Connection to ubuntu closed.

Аналогично, при удаленном доступе по протоколу SSH программа sshd, выполняясь в качестве диспетчера  в одном процессе, на каждое подключение порождает один свой клон, который, выполнив аутентификацию и авторизацию пользователя в системе, порождает еще один свой клон, имперсонирующийся в пользователя и обслуживающий его запросы.

Параллельные многонитевые программы

Для управления нитями в Linux используют стандартный POSIX-интерфейс pthreads, реализующийся библиотекой W: [NPTL], которая является частью библиотеки libc (см. в примере ниже).

Интерфейс предоставляет «нитевой» вызов создания нити pthread_create, который является условным аналогом «процессных» fork и ехес, вызов завершения и уничтожения нити pthread_exit, условно аналогичный exit, и вызов получения статуса завершения нити pthread_join, условно аналогичный wait.

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

Например, WEB-сервер apache, как показано в листинге ниже, использует два многонитевых процесса по 27 нитей в каждом, что позволяет экономить память (за счет работы всех нитей процесса с общей памятью) при обслуживании большого количества одновременных клиентских подключений.

Параллельные многонитевые сервисы

fitz@ubuntu:~$ ps f -С apache2

PID    TTY           STAT        TIME     COMMAND
21352     ?                 Ss              0:00     /usr/sbin/apache2 -k start
21355     ?                 S                0:00     \_ /usr/sbin/apache2 -k start
21357     ?                 Sl               0:00     \_ /usr/sbin/apache2 -k start
21358     ?                Sl                0:00     \_ /usr/sbin/apache2 -k start
fitz@ubuntu:~$ ps fo pid,nlwp,cmd -C apache2
PID    NLWP   CMD
21352     1            /usr/sbin/apache2 -k start
21355     1             \_ /usr/sbin/apache2 -k start
21357     27           \_ /usr/sbin/apache2 -k start
21358     27          \_ /usr/sbin/apache2 -k start 1

fitz@ubuntu:~$ ps -fLC rsyslogd
UID        PID      PPID       LWP      C      NLWP      STIME     TTY                 TIME        CMD
syslog     936             1         936       0               4          Nov19    ?                00:00:01        rsyslogd -c5
syslog     936             1         961       0               4           Nov19    ?                00:00:14        rsyslogd -c5
syslog     936             1         962       0              4            Nov19   ?               00:00:00        rsyslogd -c5
syslog     936             1         963       0              4            Nov19   ?                00:00:01        rsyslogd -c5

Аналогично, сервис централизованной журнализации событий rsyslogd использует нити дли параллельного сбора событийной информации из разных источников, ее обработки и журнализации.

Одна нить считывает события ядра из /proc/kmsg, вторая принимает события других служб из файлового сокета /dev/log, третья фильтрует поток приятных событий и записывает в журнальные файлы каталога /var/log/* и т. д.

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

Распараллеливание используется не только для псевдоодновременного выполнения ветвей параллельной программы, но и для их настоящего одновременного выполнения несколькими центральными процессорами. В примере из листинга ниже показано, как сокращается время сжатия ISO-образа файла при использовании параллельного упаковщика pbzip2 по сравнению с последовательным bzip2.

Для измерения времени упаковки применяется встроенная команда интерпретатора time, при этом сначала измеряется время упаковки и время распаковки последовательным упаковщиком, а затем — время упаковки и время распаковки параллельным упаковщиком.

Команды упаковки запускаются на «заднем фоне», оценивается наличие процессов и нитей паковщиков, после чего они переводятся на «передний фон» встроенной командой интерпретатора fg (foreground) и оцениваются затраты времени.

Параллельные многонитевые утилиты

iltz@ubuntu:~$ ls -lh plan9.iso

-rw-r—r— 1  fitz  fitz 287M нояб. 28 15:47 plan9.1so
fltz@ubuntu:~$ time bzip2 plan9.iso &
[1] 5545
fitz@ubuntu:~$ ps f
PID    TTY           STAT         TIME     COMMAND
4637   pts/0          S                0:00        -bash
5545   pts/0          S                0:00        \_ -bash
5546   pts/0          R                0:12         |      \_ bzip2 plan9.iso
5548   pts/0          R+             0:00        \_ ps f

fttz@ubuntu:~$ ps -fLp 5546

UID              PID      PPID      LWP    C     NLWP   STIME  TTY              TIME    CMD

fitz                5546     5545      5546   96             1     10:50    pts/0     00:00:22     bzip2 plan9.1so

fitz@ubuntu:~$ fg

time bzip2 plan9.iso

real 0m54.780s

user 0m51.772s

sys 0m0.428s

fitz@ubuntu:~$ ls -Ih plan9.iso.bz2

-rw-r—r— 1 fitz fitz 89M нояб. 28 15:47 plan9.iso.bz2

fitz@ubuntu:~$ time bzip2 -d plan9.iso.bz2

real 0m20.705s

user 0m19.044s

sys 0m1.168s

fitz@ubuntu:~$ time pbzip2 plan9.iso &

[1] 5571

fitz@ubuntu:~$ ps f

PID   TTY           STAT   TIME   COMMAND
4637    pts/0         S           0:00     -bash
5571     pts/0        S           0:00       \_ -bash
5572    pts/0        Sl           0:03       |        \_ pbzip2 plan9.iso
5580    pts/0       R+          0:00      \_ ps f

fitz@ubuntiu:~$ ps -fLp 5572

UID               PID     PPID      LWP    C    NLWP   STIME    TTY                   TIME  CMD

fitz                5572      5571      5578  92             8       10:52     pts/0         00:00:43  pbzip2 plan9.iso

fitz                 5572      5571     5579     1             8        10:52    pts/0         00:00:00 pbzip2 plan9.iso

fitz@ubuntu:~$ fg

time pbzip2 plan9.iso

real 0m24.259s

user 1m22.940s

sys 0m1.888s

fitz@ubuntu:~$ ls -lh plan9.iso.bz2

-rw-r—г— 1   fitz   fitz   89M нояб. 28 15:47 plan9.iso.bz2

fitz@ubuntu:~$ time pbzip2 -d plan9.iso.bz2

real 0m7.384s

user 0m25.972s

sys 0m1.396s

В результате оценки оказывается, что последовательный упаковщик bzip2 использует один однонитевой процесс и затрачивает ≈ 54,7 с реального времени на упаковку, из них ≈ 51,7 с проводит в пользовательском режиме user и лишь ≈ 0,4, с в режиме ядра sys (выполняя системные вызовы, например, read или write).

Соотношение между временем режимов говорит о вычислительном характере программы, т. е. о существенном превалировании времени вычислительных операций упаковки над временем операций ввода-вывода для чтения исходных данных и< записи результатов.

Это означает, что нагрузка последовательного упаковщика на центральный процессор близка к максимальной, и его параллельная реализация для псевдоодновременного выполнения ветвей (которые практически никогда не спят) лишена смысла.

Параллельный упаковщик pbzip2 использует один многонитевой процесс из восьми нитей и затрачивает » 24,4 с реального времени на упаковку, при этом ≈ 1 мин 22,9 с проводит в пользовательском режиме и ≈ 1,8 с в режиме ядра.

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

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

 

 

Добавить комментарий