ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    Розподілені обчислення на FreePascal під Windows
         

     

    Інформатика, програмування

    Розподілені обчислення на FreePascal під Windows

    Ілля Аввакумов, Freepascal.ru

    Введення. Про що ця стаття.

    Стаття присвячена питанню розробки розподілених (паралельних) обчислень з використанням компілятора FreePascal (використовувалася версія 2.0.1)

    Проблема паралельних обчислень зацікавила мене зовсім не тому що це зараз модно. Зіткнувся із завданням, коли треба було сформувати (для дальнейнего аналізу) великий масив даних. Хотілося зменшити час обчислень наявними засобами. Виявляється, організувати паралельні обчислення з використанням мого улюбленого компілятора - цілком розв'язувана задача.

    Стандартом для паралельних програм для багатопроцесорних обчислювальних систем де-факто є MPI.

    Ідея MPI-програми така: паралельна програма представляється у вигляді безлічі взаємодіючих (за допомогою комунікаційних процедур MPI) процесів.

    Паралельні обчислення вимагають

    1. Підрозділи процесів

    2. Взаємодія між ними

    MPI (Message Passing Interface) - стандарт на програмний інструментарій для забезпечення зв'язку між гілками паралельного додатка.

    В цій статті розглядається MPICH (MPI CHameleon), що вільно розповсюджується реалізація MPI. Використовувалася версія MPICH 1.2.5 для Windows.

    Встановлення та налаштування MPICH.

    MPICH для Windows вимагає

    1. Windows NT4/2000/XP ( Professional або Server). Під Win9x/ME працювати не буде!

    2. Мережеве підключення по протоколу TCP/IP між машинами.

    Відразу обговорити, що всі приклади тестувалися на двох машинах, об'єднаних у локальну мережу. Один комп'ютер (мережне ім'я ILYA) - мій, а другий (мережне ім'я EKATERINA) - дружини.

    Установка.

    Комп'ютери, що беруть участь в обчисленнях, назвемо кластером. MPICH повинен бути встановлений на кожному комп'ютері в кластері.

    Для установки потрібно

    1. Завантажити mpich.nt.1.2.5.src.exe (5278 Кб) або mpich.nt.1.2.5.src.zip (5248 Кб)

    Або з офіційної сторінки MPICH

    http://www.mcs.anl.gov/mpi/mpich/download.html

    Або з ftp сервера ftp.mcs.anl.gov/pub/mpi/nt.

    2. Якщо запустити exe файл, то після розпакування запуститься інтерактивна програма установки MPICH. Щоб не втомлювати себе вибором встановлюваних компонент, зручніше встановити MPICH в неінтерактивному режимі.

    Для цього

    а. Разархівіруйте вміст до спільної папки (наприклад, ILYAcommon)

    b. Відредагуйте файл setup.iss

    c. Рядок

    szDir = C: Program FilesMPICH

    визначає каталог, куди встановиться MPICH. Це розташування можна змінити.

    d. Строки

    Component-count = 7

    Component-0 = runtime dlls

    Component-1 = mpd

    Component-2 = SDK

    Component-3 = Help

    Component-4 = SDK.gcc

    Component-5 = RemoteShell

    Component-6 = Jumpshot

    визначають число встановлюваних компонент. Для головного комп'ютера (звідки запускається головний процес) відповідні опції такі

    Component-count = 4

    Component-0 = runtime dlls

    Component-1 = mpd

    Component-2 = SDK

    Component-3 = Help

    Для простого комп'ютера (якому відводиться лише роль обчислювача) число компонент може бути скорочено до двох.

    Component-count = 2

    Component-0 = runtime dlls

    Component-1 = mpd

    На кожному комп'ютері кластеру виконати команду установки в неінтерактивному режимі. У моєму випадку запуск програми установки такий:

    > ILYAcommonsetup -s-f1ILYAcommonsetup.iss

    Після встановлення на кожному комп'ютері має запуститися служба mpich_mpd (MPICH Daemon (C) 2001 Argonne National Lab). (дивіться малюнок)

    Якщо був встановлений компонент SDK (що необхідно зробити на тому комп'ютері, звідки буде проводитися запуск програм), то в каталозі MPICH (прописаному в пункті szDir) присутні підкаталоги SDK і SDK.gcc. Вміст цих каталогів -- бібліотечні та заголовки для мов C, С + + та Fortran.

    Каталог SDK призначений для компіляторів MS VC + + 6.x і Compaq Visual Fortran 6.x, а каталог SDK.gcc - для компіляторів gcc і g77.

    Налаштування

    Настройку можна здійснити за допомогою простих утиліт, що є в дистрибутиві.

    Зупинимося докладніше на каталозі mpdbin в директорії MPICH. Вміст каталогу:        

    mpd.exe         

    виконуваний файл служби mpich_mpd         

    потрібна             

    MPIRun.exe         

    файл, який здійснює запуск кожної MPI-програми.         

    потрібна             

    MPIRegister.exe         

    програма для шифрування паролів при обміні даними по   LAN.         

    іноді корисна             

    MPDUpdate.exe         

    програма для оновлення бібліотек MPI         

    не потрібна             

    MPIConfig.exe         

    програма налаштування хостів у кластері         

    не потрібна             

    guiMPIRun.exe         

    GUI версія mpirun.         

    не потрібна             

    MPIJob.exe         

    програма для управління MPI-процесами         

    не потрібна             

    guiMPIJob.exe         

    GUI версія mpijob.exe         

    не потрібна     

    Використання команд mpirun і mpiregister чекає нас попереду. Щоб упевнитися, що служби MPICH, що працюють на різних комп'ютерах, взаємодіють належним чином, можна скористатися утилітою MPIconfig. Для цього слід

    1. Запустити MPIConfig.exe (можна скористатися посиланням у головному меню, вона там повинна бути)

    2. Натиснути на кнопку "Select"

    3. У вікні, що з'явилося вибрати пункт меню "Action" - "Scan hosts"

    4. Навпаки імені кожної машини повинна зайнятися піктограма "MPI" ( приблизно ось так)

    Модуль mpi на FreePascal.

    Всі вищеописане відносилося до установки власне MPICH. Для того, щоб прикрутити бібліотеки MPICH до FreePascal, варто ще трохи попрацювати.

    Cледует скористатися динамічної бібліотекою mpich.dll, яка розташовується в системному каталозі (копіюється туди при установці MPICH).

    1. Завантажити модуль FreePascal, що реалізує функції цієї динамічної бібліотеки. Файл mpi.pp завантажити zip-архів (10 КБ)

    2. Для використання модуля mpi слід просто скопіювати файл mpi.pp у каталог де FreePascal шукає модулі (unit searchpath).

    Модуль написаний з використанням утиліти h4pas.exe і заголовків файлів *. h з SDKInclude.

    Найпростіша MPI програма на FreePascal.

    Під іменах всіх функціях бібліотеки MPICH використовується префікс MPI_. Повертане значення більшості функцій - 0, якщо виклик був успішним, а інакше - код помилки.

    Основні функції.

    Основні функції MPI, за допомогою яких можна організувати паралельне обчислення        

    1         

    MPI_Init         

    підключення до MPI             

    2         

    MPI_Finalize         

    завершення роботи з MPI             

    3         

    MPI_Comm_size         

    визначення розміру області взаємодії             

    4         

    MPI_Comm_rank         

    визначення номеру процесу             

    5         

    MPI_Send         

    стандартна блокуюча передача             

    6         

    MPI_Recv         

    блокуючий прийом     

    Стверджується, що цього вистачить. Причому перші чотири функції повинні викликатися тільки один разів, а власне взаємодія процесів - це останні два пункти.

    Опис функцій, що здійснюють передачу, залишимо на потім, а зараз розглянемо опис функцій ініціалізації/завершення

    function MPI_Init (var argc: longint;

    var argv: ppchar): longint;

    Ініціалізація MPI. Аргументи argc і argv -- змінні модуля system, що визначають число параметрів командного рядка і самі ці параметри, відповідно.

    При успішному виконанні функції MPI_Init створюється комунікатор (область взаємодії процесів), під ім'ям MPI_COMM_WORLD.

    function MPI_Comm_size (comm: MPI_Comm;

    var nump: longint): longint;

    Визначає число процесів, що входять в комунікатор comm.

    function MPI_Comm_rank (comm: MPI_Comm;

    var proc_id: longint): longint;

    Визначається ранг процесу всередині комунікатора. Після виклику цієї функції всі процеси, запущені завантажувачем MPI-програми, отримують свій унікальний номер (значення що підлягає поверненню змінної proc_id у всіх різне). Після виклику функції MPI_Comm_rank можна, таким чином, призначати різним процесам різні обчислення.

    functionnn MPI_Finalize: longint;

    Завершує роботу з MPI.

    Порядок виклику такий:

    1. MPI_Init - підключення до MPI

    2. MPI_Comm_size - визначення розміру області взаємодії

    3. MPI_Comm_rank - визначення номеру процесу

    4. Далі йде будь-яка сукупність команд обміну (передача, прийом, і тп.)

    5. MPI_Finalize - завершення роботи з MPI

    Найпростіша MPI програма така.

    test.pas

    uses mpi;

    var namelen, numprocs, myid: longint;

    processor_name: pchar;

    begin

    MPI_Init (argc, argv);

    MPI_Comm_size (MPI_COMM_WORLD, numprocs);

    MPI_Comm_rank (MPI_COMM_WORLD, myid);

    GetMem (processor_name, MPI_MAX_PROCESSOR_NAME +1);// константа MPI_MAX_PROCESSOR_NAME дорівнює 256

    namelen: = MPI_MAX_PROCESSOR_NAME;

    MPI_Get_processor_name ( processor_name, namelen);

    Writeln ( 'Hello from', myid, 'on', processor_name);

    FreeMem (processor_name);

    MPI_Finalize;

    end.

    Тут, як видно, ніякого обміну немає, кожен процес тільки "доповідає" свій ранг.

    Для наочності виводиться також ім'я комп'ютера, де кожен запущений процес. Для його визначення використовується функція MPI_Get_processor_name.

    function MPI_Get_processor_name ( proc_name: Pchar;

    var name_len: longint): longint;

    При успішному виклику цієї функції мінлива proc_name містить рядок з ім'ям комп'ютера, а name_len - довжину цього рядка.

    Після компіляції (з відповідними опціями)

    > fpc -dRELEASE [-Fu <каталог, де розміщено файл mpi.pp>] test.pas

    повинен з'явитися виконуваний файл test.exe, проте рано радіти. Запуск цього exe-файлу не є запуск паралельної програми.

    Запуск MPI-програми.

    Запуск MPI-програми здійснюється за допомогою завантажувача програми mpirun. Формат виклику такий:

    > mpirun [ключі mpirun] програма [ключі програми]

    Ось деякі з опцій команди mpirun:        

    -np x             

    запуск x процесів. Значення x може не збігатися з числом   комп'ютерів у кластері. У цьому випадку на деяких машинах запуститься   кілька процесів. Те, як вони будуть розподілені, mpirun вирішить сам   (залежить від установок, зроблених програмою MPIConfig.exe)             

    -localonly x             

    -np x-localonly             

    запуск x процесів тільки на локальній машині             

    -machinefile filename             

    використовувати файл з іменами машин             

    -hosts n   host1 host2 ... hostn             

    -hosts n   host1 m1 host2 m2 ... hostn mn             

    запустити на n явно зазначених машинах. Якщо при цьому явно   вказати число процесів на кожній з машин, то опція-np стає   необов'язковою             

    -map drive: hostshare             

    використовувати тимчасовий диск             

    -dir   drive: myworkingdirectory             

    запускати процеси у вказаній директорії             

    -env   "var1 = val1 | var2 = val2 | var3 = val3 ..."             

    присвоїти значення змінних оточення             

    -logon             

    запитати ім'я користувача і пароль             

    -pwdfile filename             

    використовувати вказаний файл для зчитування імені   користувача та пароля.   

    Перший рядок у файлі повинна містити ім'я користувача, а   другий - його пароль)             

    -nocolor             

    придушити висновок від процесів різними кольорами             

    -priority class [: level]             

    встановити клас пріоритету процесів і, опціонально,   рівень пріоритету.   

    class =   0,1,2,3,4 = idle, below, normal, above, high   

    level =   0,1,2,3,4,5 = idle, lowest, below, normal, above, highest             

    за замовчуванням використовується-priority 1:3, то є дуже   низький пріоритет.     

    Для організації паралельного обчислення на декількох машинах слід

    1. На кожному комп'ютері, що входить в кластер, завести користувача з одним і тим же ім'ям (наприклад, MPIUSER) та паролем (я дав йому пароль "1"), з обмеженими привілеями.

    2. На головному комп'ютері (в моєму випадку це, зрозуміло, ILYA) створити мережеву папку (наприклад, COMMON). Слід потурбуватися, щоб користувач MPIUSER мав до неї повний доступ.

    3. В той же папці створити файл, що містить ім'я користувача, від чийого імені будуть запускатися процеси, а також його пароль. У моєму випадку вміст цього файлу має бути таким:

    mpiuser

    1

    Я назвав це файл lgn.

    Після всіх цих дій запуск MPI програми test здійснити можна як

    > mpirun-pwdfile ILYACOMMONlgn-hosts 2 ILYA 1 EKATERINA 1 ILYACOMMONtest.exe

    Змінивши відповідні опції, можна запускати різне число процесів. Наприклад

    > mpirun-pwdfile ILYACOMMONlgn-hosts 2 ILYA 3 EKATERINA 3 ILYACOMMONtest.exe

    На малюнку видно результат такого дзвінка. Висновок від різних процесів виділяється різним кольором, оскільки опція-nocolor відключена. Зверніть увагу на те, що послідовність номер виводиться рядка зовсім не збігається з номером процесу. Цей порядок буде змінюватися від випадку до випадку.

    На цьому малюнку зображено Диспетчер завдань під час запуску на комп'ютері EKATERINA чотирьох процесів. Встановлено пріоритет за замовчуванням.

    Утиліта MPIRegister.exe.

    Оскільки комп'ютери ILYA і EKATERINA об'єднані в локальну мережу, у мене немає ніяких проблем з безпекою. Пароль для користувача mpiuser зберігається у відкритому вигляді у файлі lgn. На жаль, так можна робити далеко не завжди. Якщо комп'ютери, що входять в кластер, є частиною більш розгалуженої мережі, або, більше того, використовують підключення до Internet, так робити не просто не бажано, а неприпустимо.

    В таких випадках слід зберігати пароль користувача, від імені якого будуть запускатися процеси, в системному реєстрі Windows в зашифрованому вигляді. Для цього призначена програма MPIRegister.exe.

    Опції такі        

    mpiregister             

    Запит ім'я користувача і пароль (двічі). Після   введення запитує, зробити чи установки постійними. При відповіді 'yes' дані   будуть збережені на диску, а інакше - залишаться в оперативній пам'яті і при   перезавантаження буде втрачено.             

    mpiregister-remove             

    Видаляє дані про користувача і пароль.             

    mpiregister-validate             

    Перевіряє правильність збережених даних.     

    Запускати mpiregister слід тільки на головному комп'ютері. Завантажувач програми mpirun без опції-pwdfile буде запитувати дані, збережені програмою mpiregister. Якщо таких не виявить, то запитає ім'я користувача і пароль сам.

    Більш складні програми.

    Зараз, коли запрацювала найпростіша програма, можна почати освоювати функції обміну даними - саме те, що дозволяє здійснити взаємодія між процесами.

    Опції двоточковим обміну.

    блокуюча передача (прийом) - означає, що програма припиняє своє виконання, до тих пір, поки передача (прийом) не завершиться. Це гарантує саме той порядок виконання операцій передачі (прийому), який заданий в програмі.

    блокуюча передача здійснюється за допомогою функції MPI_Send.

    function MPI_Send (buf: pointer;

    count: longint;

    datatype: MPI_Datatype;

    destination: longint;

    tag: longint;

    comm: MPI_Comm): longint;

    Здійснює передачу count елементів зазначеного типу процесу під номером destination.        

    buf         

    - адреса першого елемента в буфері передачі             

    count         

    - кількість переданих елементів у буфері             

    datatype         

    - MPI-тип цих елементів             

    destination         

    - ранг процесу-одержувача (приймає значення від нуля до   n-1, де n - повне число процесів)             

    tag         

    - тег повідомлення             

    comm         

    - комунікатор     

    В як MPI-типу слід вказати один із зазначених нижче типів. Більшості базових типів Паскаля відповідає свій MPI-тип. Усі вони перераховані у наступній таблиці. Останній стовпчик вказує на кількість байт, необхідних для зберігання однієї змінної відповідного типу.        

    MPI_CHAR         

    shortint         

    1             

    MPI_SHORT         

    smallint         

    2             

    MPI_INT         

    longint         

    4             

    MPI_LONG         

    longint         

    4             

    MPI_UNSIGNED_CHAR         

    byte         

    1             

    MPI_UNSIGNED_SHORT         

    word         

    2             

    MPI_UNSIGNED         

    longword         

    4             

    MPI_UNSIGNED_LONG         

    longword         

    4             

    MPI_FLOAT         

    single         

    4             

    MPI_DOUBLE         

    double         

    8             

    MPI_LONG_DOUBLE         

    double         

    8             

    MPI_BYTE         

    untyped data         

    1             

    MPI_PACKED         

    складовою тип         

    -     

    Змінна tag - допоміжна цілочисельних змінна.

    MPI-тип MPI_PACKED використовується при передачі даних похідних типів (сконструйованих з базових типів). Їх розгляд виходить за рамки цієї статті.

    Функція MPI_Recv реалізує блокуючий отримання даних.

    function MPI_Recv (buf: pointer;

    count: longint;

    datatype: MPI_Datatype;

    source: longint;

    tag: longint;

    comm: MPI_Comm;

    var status: MPI_Status): longint;        

    buf         

    - початкова адреса буфера прийому             

    count         

    - максимальна кількість прийнятих елементів у буфері             

    datatype         

    - MPI-тип цих елементів             

    source         

    - ранг джерела             

    tag         

    - тег повідомлення             

    comm         

    - комунікатор             

    status         

    - статус обміну     

    Ця функція здійснює запит на отримання даних. При її виклику процес буде очікувати надходження даних від процесу під номером source. Якщо та?? овой НЕ буде, то це призведе до повісанію програми (глухий кут). Так що при використання цих функцій слід проявляти пильність.

    Число прийнятих елементів може бути менше значення змінної count. Якщо ж посилають дані мають більший розмір, то буде виведено попередження про обривання передачі.

    Возвращаемая мінлива status містить інформацію про передачу. Наприклад, її можна використовувати, щоб визначити фактичну кількість прийнятих елементів. Для цього використовується функція MPI_Get_count

    function MPI_Get_count (var status: MPI_Status;

    datatype: MPI_Datatype;

    var count: longint): longint;

    Число фактично прийнятих елементів - у повертається змінної count.

    Використання функцій двоточковим обміну.

    В наступному прикладі обчислення значень елементів масиву "розлучається" по двох процесів

    uses mpi;

    const num = 10;

    var

    teg, numprocs, myid: longint;

    i: longint;

    status: MPI_Status;

    z, x: double;

    arr: array [0 .. num] of double;

    function f (x: double): double;

    begin

    f: = sqr (x);

    end;

    begin

    MPI_Init (argc, argv);

    teg: = 0;

    MPI_Comm_size (MPI_COMM_WORLD, numprocs);

    MPI_Comm_rank (MPI_COMM_WORLD, myid);

    for i: = 0 to num do

    case myid of

    0:

    if i mod 2 = 0 then arr [i]: = f (1.0 * i)

    else

    begin

    MPI_Recv (@ x, 1, MPI_DOUBLE, 1, teg, MPI_COMM_WORLD, status);

    arr [i]: = x

    end;

    1:

    if i mod 2 = 1 then

    begin

    z: = f (1.0 * i);

    MPI_Send (@ z, 1, MPI_DOUBLE, 0, teg, MPI_COMM_WORLD);

    end;

    end;// case statement

    if myid = 0 then for i: = 0 to num do writeln (i, '', arr [i ]);

    MPI_Finalize;

    end.

    Формується масив певної кількості елементів так, що елементи з парними номерами розраховує процес з myid = 0, а непарними - з myid = 1. Звичайно, замість функції sqr може стояти будь-яка інша. Програма написана, звичайно ж, у розрахунку на те, що процесів буде всього два. Оскільки значення myid, відмінні від 0 і 1, не використовуються, процеси з такими номерами будуть простоювати.

    Поліпшити програму, тобто написати такий її варіант, щоб використовувалися всі процеси, надаю читачеві:)

    Опції колективного обміну.

    Колективний обмін даними зачіпає не два процеси, а всі процеси всередині комунікатора.

    Найпростішими (і найбільш часто використовуваними) різновидами такого виду взаємодії процесів є розсилка MPI_Bcast і колективний збір даних MPI_Reduce.

    function MPI_Bcast (buff: pointer;

    count: longint;

    datatype: MPI_Datatype;

    root: longint;

    comm: MPI_Comm): longint;        

    buf         

    - адреса першого елемента буфера передачі             

    count         

    - максимальна кількість прийнятих елементів у буфері             

    datatype         

    - MPI-тип цих елементів             

    root         

    - ранг джерела розсилки             

    comm         

    - комунікатор     

    Функція MPI_Bcast реалізує "трансляцію передачу". Один процес ( головний або root процес) розсилає всім (і собі, у тому числі) повідомлення довжини count, а інші отримують це повідомлення.

    function MPI_Reduce (buf: pointer;

    result: pointer;

    count: longint;

    datatype: MPI_Datatype;

    operation: MPI_Op;

    root: longint;

    comm : MPI_Comm): longint;        

    buf         

    - адреса першого елемента буфера передачі             

    count         

    - кількість елементів у буфері передачі             

    datatype         

    - MPI-тип цих елементів             

    operation         

    - операція приведення             

    root         

    - ранг головного процесу             

    comm         

    - комунікатор     

    Функція MPI_Reduce виконує операцію приведення над масивів даних buf, отриманими від всіх процесів, і пересилає результат у result одному процесу (ранг якого визначений параметром root).

    Як і функція MPI_Bcast, ця функція повинна викликатися всіма процесами в заданому комунікаторі, і аргументи count, datatype і operation повинні збігатися.

    Є 12 наперед визначених операцій приведення        

    MPI_MAX         

    максимальне значення             

    MPI_MIN         

    мінімальне значення             

    MPI_SUM         

    сумарне значення             

    MPI_PROD         

    значення твори всіх елементів             

    MPI_LAND         

    логічне "і"             

    MPI_BAND         

    побітове "і"             

    MPI_LOR         

    логічне "або"             

    MPI_BOR         

    побітове "або"             

    MPI_LXOR         

    логічне що виключає "або"             

    MPI_BXOR         

    побітове що виключає "або"             

    MPI_MAXLOC         

    індекс максимального елементу             

    MPI_MINLOC         

    індекс мінімального елементу     

    Використання колективних функцій (обчислення числа

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status