Современные информационные технологии/Вычислительная техника и программирование

Мясищев А.А.

Хмельницкий национальный университет, Украина

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

 

При решении ряда прикладных задач, описываемых дифференциальными уравнениями в частных производных, возникает необходимость в перемножении квадратных матриц большого порядка и решении систем линейных уравнений. В частности при решении задач теории упругости, пластичности, которые сводятся к решению систем дифференциальных уравнений в напряжениях и скоростях, используется метод конечных элементов. В свою очередь данный метод сводится к построению матриц жесткости, перемножению матриц и решению систем линейных уравнений, содержащей тысячи и даже десятки тысяч неизвестных. При решении пластических задач решение таких задач приходится выполнять сотни и тысячи раз для выявления конечной конфигурации деформируемого материала. Это требует вычислительных систем высокой производительности. В настоящее время широкое распространение получили компьютеры с многоядерными процессорами. Например, двуядерные и четырехядерные процессоры фирмы Intel (E2160, Q6600) и AMD(Athlon 64x2 4000+). Причем прогрессирование технологии производства процессоров в настоящее время идет о пути увеличения числа ядер. И как отмечают производители, обычный персональный компьютер с одним из таких процессоров превращается в параллельную вычислительную систему с общей памятью (SMP-система). Проблема заключается в том, чтобы распараллелить, например задачи решения систем линейных уравнений и перемножения матриц так, чтобы получить максимальную загрузку многоядерного процессора и выигрыш в производительности примерно соответствующий числу ядер. Параллельно многоядерным системам также развиваются и кластерные системы с распределенной памятью, соединенные между собой быстродействующими коммуникациями. При параллельном решении задач на этих системах неизбежно решается задача о пересылке данных между процессами, и чем выше скорость пересылок, тем эффективнее распараллеливание. 

Основой для параллельного выполнения программ для параллельных вычислительных систем является модель передачи сообщений. В этой модели параллельная программа представляет собой систему процессов, которые функционируют независимо друг от друга. Взаимодействие процессов через среду передачи данных (компьютерную сеть, разделяемую память) требует дополнительных затрат времени. Обмены между процессорами в параллельной системе происходят путем передачи через коммуникационную среду численной или иной информации. Существует две основные характеристики коммуникационных сред: латентность – время  начальной задержки при посылке сообщений и пропускная способность коммуникационной системы, определяющая скорость передачи информации между процессорами. При решении реальных параллельных задач важны реальные, а не пиковые характеристики, которые достигаются, например, при решении задач методом MPI. Так, например, после вызова функции посылки сообщения оно последовательно пройдет через набор слоев, определяемых особенностями реализации ПО и аппаратуры, прежде чем сообщение покинет процессор.  Это порождает латентность. Следовательно, максимальная скорость передачи через коммуникационную среду достигается на больших сообщениях, когда доля  времени латентности  в процессе передачи полного набора данных мала.

         Рассмотрим количественные характеристики межпроцессорного обмена.

Пропускная способность среды передачи представляет собой количество информации, передаваемой между узлами в единицу времени (байт в секунду). Латентностью называется время, затрачиваемое программным обеспечением и устройствами, по которым осуществляется обмен информацией, на подготовку к передаче сообщений по данному каналу. Латентность (задержка) — один из основных показателей эффективности коммуникационной инфраструктуры параллельной системы (кластера). Эта задержка включает в себя программный компонент (задержка, определяемая стеком протоколов TCP/IP, а также возможные накладные расходы, связанные с копированием передаваемых данных из буферов пользователя в буферы ядра операционной системы) и аппаратный компонент. В последний, кроме задержек на портах коммутаторов, входят и задержки на сетевых платах. Латентность измеряется как время, необходимое на передачу сигнала или сообщения нулевой длины. При измерении латентности для снижения влияния погрешности и низкого разрешения системного таймера важно повторить операцию посылки сигнала и получения ответа большое число раз.

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

При проведении опытных исследований рассматривались компьютерные системы на базе процессоров Intel: Q6600, E2160; AMD Athlon 64x2 4000+. Для определения скорости пересылок два компьютера с процессором Q6600 объединялись через коммутатор DES-3326SR  фирмы DLink с целью обеспечения сетевого взаимодействия по сети Ethernet  со скоростями 100Мбит/с и 1000Мбит/с . В другом случае компьютеры с процессорами Q6600, E2160  и Athlon 64x2 4000+ работали в автономном режиме для определения скорости пересылок между ядрами процессора. В обоих случаях определялось время латентности и скорости пересылок для массивов двойной точности разной длины. Скорости пересылок (но не латентность) сравнивались со скоростями передачи данных при копировании массивов в оперативной памяти для одного процесса, который выполнялся в одном ядре. Затем рассчитывались отношения времен пересылок между процессами по технологии MPI  и пересылками внутри памяти. Опыты проводились с использованием операционной системы PelicanHRC GNU/Linux v.1.7.2., которая запускается как “live CD”.  При ее установке на узловые компьютеры организуется высокопроизводительная параллельная кластерная система с использованием MPI. Ниже представлена программа по определению времени латентности и скорости передачи сообщений между процессорами для двунаправленных пересылок, которая  написана на языке FORTRAN:

 

      program latentnost

      include 'mpif.h'

      integer ierr, rank, size, i, n, lmax, NMAX, NTIMES

      parameter (NMAX = 1000000, NTIMES = 100)

      double precision time_start, time_stop,time, bandwidth

      real*8 a(NMAX),b(NMAX),t(1000),t1(1000)

      integer status(MPI_STATUS_SIZE)

      call MPI_INIT(ierr)

      call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr)

      call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)

c Задание исходных данных

      n =0

      ii=1

      do ia=1,NMAX

      a(ia)=ia*1.0d0

      end do

c  Начало цикла расчета

      do while (n.le.NMAX)

c  NTIMES пересылок для осреднения результата

      if(rank .eq. 0) then

      time_start = MPI_WTIME(ierr)

      do i = 1, NTIMES

      call MPI_SEND(a, n, MPI_DOUBLE_PRECISION, 1, 1,

     &   MPI_COMM_WORLD, ierr)

      call MPI_RECV(a, n, MPI_DOUBLE_PRECISION, 1, 1,

     &   MPI_COMM_WORLD, status, ierr)

      time = (MPI_WTIME(ierr)-time_start)/2/NTIMES

      bandwidth = (8*n*1 .d0/(2**20))/time

      end do

      end if

      if(rank.eq.1) then

      do i = 1, NTIMES

      call MPI_RECV(b, n, MPI_DOUBLE_PRECISION, 0, 1,

     &MPI_COMM_WORLD, status, ierr)

      call MPI_SEND(b, n, MPI_DOUBLE_PRECISION, 0, 1,

     &  MPI_COMM_WORLD, ierr)

      end do

      end if

c  Конец NTIMES пересылок для осреднения результата

c  Расчет времени двойной пересылки и скорости в МБайт/с

c

      if(rank .eq. 0) then

      if(n .eq. 0) then

c Если длина пересылаемых данных равна нулю, то это латентность

      print *, 'latency = ', time, ' seconds'

c В другом случае распечатывается длина сообщения и скорость

      else

      print *, 8*n, ' bytes, bandwidth =', bandwidth,

    & ' Mb/s',' time=', time, ' n=',n

      t(ii)=time

      ii=ii+1

      end if

      end if

c

      if (n.eq.0) then

      n=1

      else

      n=2*n

      end if

      end do

c   Конец цикла расчета

      n=1

c   Расчет для одного процесса в оперативной памяти

      if(rank .eq. 0) then

      ii=1

      print *, 'Memory'

      do while (n.le.NMAX)

      time_start = MPI_WTIME(ierr)

      do i=1,NTIMES

      do j=1,n

      b(j)=a(j)

      end do

      do j=1,n

      a(j)=b(j)

      end do

      end do

      time_stop=MPI_WTIME(ierr)

      time=(time_stop-time_start)/2/NTIMES

      bandwidth = (8*n*1 .d0/(2**20))/time

      print *, 8*n, ' bytes, bandwidth =', bandwidth,

     & ' Mb/s',' time=', time, ' n=',n

      t1(ii)=time

      ii=ii+1

      n=2*n

      end do

      do m=1,ii-1

c Определение отношения времен пересылки между процессами и памятью

      tim=t(m)/t1(m)

      print *,'proc/mem=',tim

      end do

      end if

      call MPI_FINALIZE(ierr)

      end

 

         При составлении программы использовался интерфейс обмена сообщениями (Message Passing Interface, MPI). Ниже представлены основные функции, которые задействованы в программе:

 

MPI_INIT (IERROR)

Функция завершения MPI программ MPI_Finalize

 

MPI_FINALIZE (IERROR)

Функция закрывает все MPI-процессы и ликвидирует все области связи.  Параметр IERROR является выходным и возвращает код ошибки.

 

Функция определения числа процессов в области связи MPI_COMM_SIZE:

MPI_COMM_SIZE (MPI_COMM_WORLD, SIZE, IERROR)

MPI_COMM_WORLD - коммуникатор;

SIZE - число процессов в области связи коммуникатора MPI_COMM_WORLD.

 

Функция определения номера процесса MPI_COMM_RANK:

MPI_COMM_RANK (MPI_COMM_WORLD, RANK, IERROR)

MPI_COMM_WORLD - коммуникатор;

RANK - номер процесса, вызвавшего функцию.

Номера процессов лежат в диапазоне 0..SIZE-1 (значение SIZE может быть определено с помощью предыдущей функции).

 

Функция передачи сообщения MPI_SEND:

MPI_SEND (BUF, COUNT, DATATYPE, DEST, TAG, MPI_COMM_WORLD, IERROR)

BUF - адрес начала расположения пересылаемых данных (массив или скалярная величина);

COUNT - число пересылаемых элементов (для скалярной величины COUNT=1);

DATATYPE  -  тип посылаемых элементов (MPI_REAL, MPI_DOUBLE_PRECISION, MPI_INTEGER);

DEST  -      номер процесса-получателя в группе, связанной с коммуникатором MPI_COMM_WORLD;

TAG - идентификатор сообщения;

MPI_COMM_WORLD - коммуникатор области связи.

 

Функция приема сообщения - MPI_RECV

MPI_RECV (BUF, COUNT, DATATYPE, SOURCE, TAG, MPI_COMM_WORLD,

STATUS, IERROR)

BUF - адрес начала расположения принимаемого сообщения;

COUNT - максимальное число принимаемых элементов;

DATATYPE - тип элементов принимаемого сообщения;

SOURCE - номер процесса-отправителя;

TAG - идентификатор сообщения;

MPI_COMM_WORLD - коммуникатор области связи;

STATUS (MPI_STATUS_SIZE) - массив атрибутов приходящего сообщения. В Фортране параметр STATUS является целочисленным массивом размера MPI_STATUS_SIZE. Константы MPI_SOURCE, MPI_TAG, MPI_ERROR - являются индексами по данному массиву для доступа к значениям соответствующих полей:

STATUS (MPI_SOURCE) - номер процесса-отправителя сообщения;

STATUS (MPI_TAG) - идентификатор сообщения;

STATUS (MPI_ERROR) – код ошибки.

 

Функция времени – таймер

MPI_WTIME()

Функция возвращает астрономическое время в секундах, прошедшее с некоторого момента в прошлом (точки отсчета). Гарантируется, что эта точка отсчета не будет изменена в течение жизни процесса. Для хронометража участка программы вызов функции делается в начале и конце участка и определяется разница между показаниями таймера.

         Для передачи данных между компьютерами с процессорами Q6600 по сети Ethernet  файл /home/user/tmp/bhosts имел следующий вид:

10.11.12.1        cpu=1

10.11.12.2        cpu=1

Для пересылок между ядрами процессоров Q6600, E2160, Athlon 64x2 4000+

10.11.12.1  cpu=2

Для перехода к разным моделям параллельных систем использовалась команда

lamboot   /home/user/tmp/bhosts

После этого выполнялась компиляция

mpif77  -O3  latentnost.f   -o  latentnost

и запуск на выполнение

mpirum  -C  latentnost

Здесь

latentnost.f   - имя программы,

-O3  - ключ оптимизации транслятора FORTRAN. Позволяет отследить эффект кэш памяти 1-го уровня

C  - запуск при использовании всех узлов кластера (ядер процессора)

Ниже представлены результаты исследований.

В таблице 1 показаны значения латентности для разных параллельных систем.

 

Таблица 1 - латентность

Система

Латентность в микросекундах

Q6600 – Fast Ethernet

47.8

Q6600 – Gigabit Ethernet

31.6

Q6600 – Memory (пересылка между ядрами)

3.9

E2160 – Memory

6.7

Athlon 64x2 4000+  - Memory    

5.5

Согласно таблице латентность для сети Ethernet в 10-15 раз выше латентности по сравнению с пересылками между ядрами процессоров через разделяемую память.

Рис.1.

         На рис.1 представлен график зависимостей скорости передачи данных для межпроцессорных коммуникаций, организованных сетями Fast Ethernet и Gigabit  Ethernet в зависимости от размера передаваемых данных. Использовалась система на базе процессоров Q6600. Результаты работы программы показывают, что при длинах пересылаемых данных больше 16000 байт скорость передачи стабилизируется значениями ~10Мбайт/с для Fast Ethernet и ~60Мбайт/с для Gigabit  Ethernet.

         На рис.2 представлен график зависимостей скоростей передачи межпроцессорных данных  для Fast Ethernet и Gigabit  Ethernet имеющих размеры до 2000 байт. Использовалась система на базе процессоров Q6600. Видно, что для размеров данных до ~200 байт  скорости передачи для Fast Ethernet и Gigabit  Ethernet примерно одинаковы, но например, для значений в1000 байт и выше скорости отличаются в два и больше число раз. 

Рис.2.

         На рис.3 представлен график зависимостей скоростей передачи межпроцессорных данных  для многоядерной системы на базе процессора Q6600 в зависимости от размера данных. Кривые 1 и 2 соответствуют пересылкам между разными массивами данных в пределах одного ядра процессора. Однако 1-я кривая построена по результатам решения при установке оптимизационного ключа  O3  при компиляции. Кривая 2 построена по результатам решения без ключа оптимизации при компиляции. Кривая 3 соответствует зависимости скорости пересылки данных между ядрами процессора от величины пересылаемых данных, полученная с использованием библиотек MPI.

Рис.3.

Видно, что чем больше объем пересылаемых данных, тем ближе скорости пересылок приближаются друг к другу. При сравнении кривых 1 и 2 видно влияние кэш памяти 1-го и 2-го уровней на скорость пересылки. Например, кэш-память 2-го уровня отчетливо прослеживается на размере пересылаемых данных длиной до 1000000 байт, после чего ее влияние уменьшается в пределе до 4000000 байт (график представлен несколько урезанным).

         На рис.4 представлен график зависимостей скоростей передачи межпроцессорных данных  для многоядерной системы на базе процессора Q6600 для малых размеров передаваемых сообщений (до 64000 байт). Как и в предыдущем случае, кривая 1 построена с ключом оптимизации –O3 и отображает интервал влияния кэш памяти 1-го уровня. Видно, что скорость пересылок в области размера данных 200-30000 байт существенно превышает скорости для двух других случаев. Однако если кривые 1 и 2 при длине данных начиная с 8 байт сразу соответствуют скоростям передачи  4000 и 2000 Мбайт/с, то 3-я кривая начинается со значений ~1 Мбайт/с постепенно увеличиваясь до 300Мбайт/с для размера пересылаемых данных  4000 байт. Это свидетельствует о том, что межъядерная пересылка данных внутри оперативной памяти очень неэффективна для размеров, соизмеримых с размерами переменных. Фактически здесь имеет место аналогичная ситуация, как и для пересылок данных малых размеров в условиях Gigabit Ethernet. Поэтому создание параллельных алгоритмов, связанных с пересылкой значений переменных (не массивов) не эффективно даже для многоядерных систем при работе с общей памятью.

Рис.4.

         На рис.5 представлен график зависимостей скоростей передачи данных при их пересылке в оперативной памяти для одного процесса между массивами для трех разных систем с процессорами:  Q6600 (1-я кривая), Athlon 64x2 4000+ (2-я кривая), E2160(3-кривая). Все кривые построены по результатам решения при установке оптимизационного ключа  O3  при компиляции. Из графика видно, что процессор Q6600 с памятью работает существенно быстрее, чем другие процессоры, однако интервал действия кэш памяти 1-го уровня у процессора Athlon больше примерно в два раза, чем у процессоров Intel, хотя она медленнее, чем у Intel.

Рис.5.

         На рис.6 представлен график зависимостей скоростей передачи данных при их пересылке в разделяемой памяти для двух процессов между ядрами с использованием MPI для трех систем с процессорами:  Q6600 (1-я кривая),  Athlon 64x2 4000+ (2-я кривая), E2160 (3-кривая).

Рис.6.

 

         Рассмотрим, как меняется отношение скоростей пересылок в зависимости от длины данных между процессами для MPI и в пределах оперативной памяти для одного процесса (в пределах ядра процессора) для систем с процессором Q6600, когда пересылки по MPI проводятся через Fast Ethernet, Gigabit Ethernet и разделяемую память.

Рис.7.

На рис.7 представлен график зависимости изменения отношения скоростей для пересылки данных размером до 4194304 байт. В конце кривых указаны минимальные значения отношений. На рис.8 представлен аналогичный график зависимости изменения отношения скоростей для пересылки данных, но размером до 1024 байт. Цифрами у каждой кривой указаны минимальные значения отношения скоростей для этого диапазона размера передаваемых данных. Расчеты выполнялись с ключом оптимизации –O3. Интересно отметить, что скорость пересылки данных  в оперативной памяти до 2000 раз выше даже скорости пересылки в  разделяемой памяти с помощью MPI, не говоря уже при обмене данными через Fast Ethernet  и  Gigabit Ethernet.

Рис.8.

         На основании изложенного материала можно сделать следующие выводы.

1.     Латентность для Gigabit Ethernet примерно в 1.5 раза меньше чем для Fast Ethernet

2.     Латентность для сети Gigabit Ethernet примерно в 10 раз выше латентности по сравнению с пересылками между ядрами процессоров через разделяемую память

3.     Увеличение в 2 и более раз скорости передачи данных для Gigabit Ethernet  по сравнению с Fast Ethernet между процессами наблюдается при размере передаваемых данных более 1000 байт.

4.      В случае использования оптимизационного ключа –O3 при компилировании программы скорость обмена внутри памяти для одного процесса существенно возрастает за счет использования кэш памяти. Особенно резко возрастает быстродействие при работе с кэш памятью 1-го уровня. При пересылке данных между ядрами процессора через общую память, кэш память не используется, поэтому для значений данных свыше 500000 байт скорости обмена внутри памяти и скорости пересылок с помощью MPI через общую память отличаются незначительно, если не использовать ключ оптимизации компилятора –O3.

5.     При создании параллельных программ даже для многоядерных процессоров, эффективность распараллеливания наблюдается лишь в случае, если размер пересылаемых данных превышает 40000 байт. В этом случае отношение времен пересылок уменьшается от 10 до 1,8 раз.

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

 

Литература.

1. Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. –СПб: БХВ – Петербург, 2004.-608 с.: ил.