Clustery pod Linuxem

Jan Horáček, xhoracek@fi.muni.cz


Obsah



1 Úvod

Clustery (někdy též označovány jako Beowulf-class computers) vznikly v podstatě před nedávnem jako snaha zvýšit výpočetní výkon za rozumnou cenu. Cluster lze (stejně jako supervýkonné multiprocesorové počítače, které jsou ale velmi nákladné) používat jako velice výkonný stroj, který je ve skutečnosti složen z několika počítačů paralelně zpracovávajících úlohy. Hlavní myšlenka tedy je vzít několik levných PC a ty spolu spojit vysokorychlostní sítí. Nad tím vším stojí jeden nebo více počítačů, se kterým uživatel komunikuje a který se jeví jako jeden server. Ten však jen převezme úlohu, podle nějakého kriteria ji rozdělí mezi počítače pod ním a uživateli vrátí výsledek. V případě nedostatku výkonu lze takovýto cluster posílit přidáním dalších strojů.

1.1 Výhody

Jak již bylo zmíněno, výhodou takovéhoto řešení je hlavně poměr ceny a výkonu systému.

1.2 Nevýhody

Nevýhody vyplývají již z použité architektury. Počíteče v clusteru nemohou mezi sebou sdílet operační paměť (na hardwarové úrovni). Jedna stanice tedy může mít kritický nedostatek paměti, zatím co jiné stanice jí mají momentálně nadbytek. To lze pouze částečně řešit za použití speciálního HW a SW ve spolupráci s vysokorychlostní sítí.
Další nevýhodou je pak chybovost. Architektura PC i síť, kterou jsou stanice spojeny, mají velmi malou průměrnou dobu mezi chybami (na rozdíl od speciálně navrhovaných superpočítačů).
V také v neposlední řadě třída úloh, které jsou řešitelné na clusterech, je spíše podmnožinou úloh řešitelnýh na superpočítačích.

1.3 Jak to začalo

Asi první PC cluster vznikl ve výzkumném centru CESDIS (Center of Excellence in Space Data and Information Sciences), kde jej v roce 1994 sestrojil Donald Beckerem. Tento PC cluster byl sestaven ze šestnácti strojů s procesory Interl 486 DX4 spojených 10Mbitovou sítí. Pojmenovali jej Beowulf.

1.4 Současnost

Do dnešního dne se clustery velmi rozšířily. Za vše hovoří žebříček 500 nejvýkonnějších počítačů světa. V současné době je nejvýkonnější cluster již na 5. místě, zatím co před dvěma lety byl nejvýkonnější cluster na 84. pozici (údaj z listopadu 2000).
Prvních pět nejvýkonnějších strojů na světě můžete vidět v následující tabulce:
Pořadí a název Popis
1. Earth Simulator Společný projekt Japonských firem NASDA, JAERI a JAMSTEC na vývoj systému promodelování klimatu.
Současný výkon: 35.86 TFlops
Hardware:
  • 5120 (640 osmicestných uzlů) 500 MHz NEC procesorů
  • 8 GFLOPS na CPU
  • 2 GB FPLRAM na CPU (celkem 10 TB)
  • sdílená paměž uvnitž uzlu
  • 640 x 640 switch mezi uzly
  • šírka pásma mezi uzly 16 GB/s
  • spotřeba jednoho uzlu 20 kVA
  • 2. a 3. ASCI Q Pátý stroj společnosti NNSA nacházející se v Los Alamos.
    Současný výkon: 7.72 TFlops
    V konečné fázi bude mít 11 968 procesorů, 12 TB paměti a 600 TB diskového prostoru.
    Jedná se o dva segmenty.
    4. ASCI WHITE Stroj se nachází v Livermoru. Současný výkon: 7.22 TFlops
    Je složen ze tří IBM RS/6000 SP systémů pojmenovaných White, Frost a Ice.
    Zabírá rozlohu dvou basketbalových hřišť a váží 106 tun.
    Obsahuje 8192 procesorů IBM RS6000 SP Power3 na frekvenci 375 MHz a má diskovou kapacitu 160 TB.
    5. MCR Linux cluster Cluster se také nachází v Livermooru.
    Současný výkon: 5.69 TFlops
    Hardware:
  • 4.6 TB celkové paměti
  • 138.2 TB diskového prostoru
  • 1152 uzlů oddělujících záložní a pracovní cluster
  • 2304 procesorů Intel Xeon taktovaných na 2.4 GHz


  • 2 Load balancing

    Load balancing (rozložení zátěže) je problém minimalizace zátěže procesoru a celkového času paralelní úlohy (nebo více úloh), která na clusteru právě běží. Stroj, který řídí cluster tedy obsahuje prvek často označovaný LBS (Load-Balance system/server), který podle definovaného algoritmu rozděluje zátěž na jednotlivé stanice. Load balancing může být realizován na síťové, transportní či aplikační vrstvě OSI modelu.

    2.1 Round-robin

    Rozdělování zátěže probíhá bez ohledu na počet spojení, úloh či odezvu systému. Požadavky se cyklicky přidělují na všechny systémy: ABCABCABC... Je to vhodné v případech, kdy víme, že výkon i zátěž jednotlivých stanic budou vyrovnány. Může zde ale docházet k tomu, že některé ze stanic budou mnohem více zatíženy než ostatní, protože není zohledněno zatížení systémů.

    2.2 Weighted round-robin

    Pracuje stejně jako round-robin, ale navíc je zde možnost stanovit váhy jednotlivým stanicím. Je to vhodné zejména v případě, kdy máme v clusteru různě výkonné stanice. Opět zde ale není zohledněna zátěž jednotlivých stanic.

    2.3 Least-connection

    Úloha bude směrována na stroj, který právě vyřizuje nejmenší počet úloh. Tento algorigmus dává dobré výsledky u celků s relativně malým provozem, ale také u systémů s různým výkonem, protože rychlejší systém zpracuje úlohu rychleji než pomalejší a je mu tedy možné posílat další úlohy.

    2.4 Weighted least-connection

    Princip je opět stejný jako u weighted round-robin, navíc má každý systém přidělenu váhu, kolik spojení z celkového počtu bude vyřizovat. Tento algoritmus používá např. LVS (Linux Virtual Server) a bývá také nejčastěji používán v praxi.

    3 Network Software Interface

    Předtím, než se přejdu na softwarovou podporu pro paralelní aplikace, uvedu možnosti, jak mezi sebou mohou jednotlivé stanice clusteru komunikovat. Jsou zde pouze tři možnosti. Sokety, ovladače zařízení a uživatelské knihovny.

    Sokety:
    Do nedávna nejpouživanéjší způsob komunikace, protože sokety jsou již dlouho součástí UNIXu a většina síťového HW je konstruována pro podporu alespoň UDP a TCP. Oba tyto typy umožňují posílat libovolnou velikost bloku dat od jedné stanice ke druhé, ale jsou samozřejmě mezi nimi rozdíly.

    Ovladače zařízení:
    Používá přímo rozhraní síťového adaptéru. Funkce driveru mohou být vyvolány uživatelským programem pomocí funkce open() pro identifikaci odpovídajícího zařízení a poté použít funkce read() a write() na otevřený "soubor". Každá takováto operace tedy může přenést blok dat s jistou dávkou režie při volání systémových služeb.



    4 User-Level knihovny

    Tyto knihovny nepoužívají volání systému, ale přímo přistupují k registrům zařízení. Na běžných systémech existují dvě možnosti: Navíc Linux nabízí pro stanice založené na architektuře Intel 386 ještě další dvě možnosti: Pro demostraci jednotlivých knihoven bude použit algoritmus pro přibližný výpočet čísla pi:

    #include ;
    #include ;
    
    main(int argc, char **argv)
    {
      register double width, sum;
      register int intervals, i;
    
      /* počet intervalů */
      intervals = atoi(argv[1]);
      width = 1.0 / intervals;
    
      /* samotný výpočet */
      sum = 0;
      for (i = 0; i < intervals; i++) {
        register double x = (i + 0.5) * width;
        sum += 4.0 / (1.0 + x * x);
      }
      sum *= width;
    
      printf("Odhad pi je %f\n", sum);
    
      return(0);
    }
    

    4.1 PVM (Parallel Virtual Machine)

    PVM je volně šiřitelná, portabilní knihovna vytvořená nad sokety, používající zasílání zpráv. Je to v podstatě standard pro tento způsob paralelních výpočtů. PVM podporuje jak jednoprocesorové stroje, tak clustery Linuxových strojů spojených sítěmi založených na soketech (např. SLIP, PLIP, Ethernet, ATM). PVM dokáže pracovat nad skupinami stroju s různými typy procesorů, konfiguracemi a fyzickými sítěmi, tedy nad heterogenními clustery.

    Příklad výpočtu pí s použitím knihovny PVM vypadá takto:
    #include 
    #include 
    #include 
    
    #define NPROC   4
    
    main(int argc, char **argv)
    {
      register double lsum, width;
      double sum;
      register int intervals, i; 
      int mytid, iproc, msgtag = 4;
      int tids[NPROC];  /* array of task ids */
    
      /* přihlášení do pvm */
      mytid = pvm_mytid();
    
      /* Přihlášení do skupiny a pokud je první instancí,
         iproc=0, vytvoří více kopií sama sebe.
      */
      iproc = pvm_joingroup("pi");
    
      if (iproc == 0) {
        tids[0] = pvm_mytid();
        pvm_spawn("pvm_pi", &argv[1], 0, NULL, NPROC-1, &tids[1]);
      }
      /* Ujistí se, že jsou přítomny všechny procesy */
      pvm_barrier("pi", NPROC);
    
      /* počet intervalů */
      intervals = atoi(argv[1]);
      width = 1.0 / intervals;
    
      lsum = 0.0;
      for (i = iproc; i < intervals; i+=NPROC) {
        register double x = (i + 0.5) * width;
        lsum += 4.0 / (1.0 + x * x);
      }
      
      sum = lsum * width;
      pvm_reduce(PvmSum, &sum, 1, PVM_DOUBLE, msgtag, "pi", 0);
    
      /* Vytiskne výsledek */
      if (iproc == 0) {
        printf("Odhad pi je %f\n", sum);
      }
    
      /* Ověří, zda program zkončil a opustí skupinu a pvm */
      pvm_barrier("pi", NPROC);
      pvm_lvgroup("pi");
      pvm_exit();
      return(0);
    }
    

    4.2 MPI (Message Passing Interface)

    Jde o relativně nový standard pro "message-passing" knihovny. Definuje syntaxi a sémantiku volání jádra knihovních funkcí a umožňuje uživatelům psát programy v jazyce C a Fortran 77. V současné době je poslední verze MPI 2.0.
    Standard MPI 1.1, který je základem většiny současných implementací MPI, je tvořen částmi, které specifikují:
  • operace dvoubodové komunikace (point-to-point communication)
  • kolektivní komunikační operace (collective operations)
  • odvozené datové typy (derived datatypes)
  • operace pro práci se skupinami procesů (process groups)
  • prostředky pro stanovení topologie procesů (process topologies)
  • vazbu na prostředí (enviromental management)
  • rozhraní jazyka C a Fortran 77.
    Navíc ve verzi MPI 2.0 např. přibylo:
  • prostředky pro vytváření a splávu procesů (process creation and management)
  • operace pro jednostrannou komunikaci (one-side communication)
  • rozšířené kolektivní komunikační operace
  • podpora vícevláknových programů
  • operace pro paralelní I/O soubory
  • rozhraní jazyka C++

    Následuje srovnání MPI a PVM: První MPI program využívá základní posílání zpráv pro každý procesor k poslání části výsledku procesoru 0, který výsledky zpracuje a vytisken výsledek:
    #include 
    #include 
    #include 
    
    main(int argc, char **argv)
    {
      register double width;
      double sum, lsum;
      register int intervals, i; 
      int nproc, iproc;
      MPI_Status status;
    
      if (MPI_Init(&argc, &argv) != MPI_SUCCESS) exit(1);
      MPI_Comm_size(MPI_COMM_WORLD, &nproc);
      MPI_Comm_rank(MPI_COMM_WORLD, &iproc);
      intervals = atoi(argv[1]);
      width = 1.0 / intervals;
      lsum = 0;
      for (i = iproc; i < intervals; i += nproc) {
        register double x = (i + 0.5) * width;
        lsum += 4.0 / (1.0 + x * x);
      }
      lsum *= width;
      if (iproc != 0) {
        MPI_Send(&lbuf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
      } else {
        sum = lsum;
        for (i = 1; i < nproc; ++i) {
          MPI_Recv(&lbuf, 1, MPI_DOUBLE, MPI_ANY_SOURCE,
                   MPI_ANY_TAG, MPI_COMM_WORLD, &status);
          sum += lsum;
        }
        printf("Odhad pi je %f\n", sum);
      }
      MPI_Finalize();
      return(0);
    }
    

    Druhá MPI verze využívá kolektivní komunikace, která je pro tento příklad asi nevhodnější:
    #include 
    #include 
    #include 
    
    main(int argc, char **argv)
    {
      register double width;
      double sum, lsum;
      register int intervals, i; 
      int nproc, iproc;
    
      if (MPI_Init(&argc, &argv) != MPI_SUCCESS) exit(1);
      MPI_Comm_size(MPI_COMM_WORLD, &nproc);
      MPI_Comm_rank(MPI_COMM_WORLD, &iproc);
      intervals = atoi(argv[1]);
      width = 1.0 / intervals;
      lsum = 0;
      for (i = iproc; i < intervals; i += nproc) {
        register double x = (i + 0.5) * width;
        lsum += 4.0 / (1.0 + x * x);
      }
      lsum *= width;
      MPI_Reduce(&lsum, &sum, 1, MPI_DOUBLE,
                 MPI_SUM, 0, MPI_COMM_WORLD);
      if (iproc == 0) {
        printf("Odhad pi je %f\n", sum);
      }
      MPI_Finalize();
      return(0);
    }
    

    A konečně třetí verze využívá MPI 2.0 mechanismus vzdáleného přístupu k paměti (RMA), kdy každý procesor přidá svůj výsledek do celkového výsledku procesoru 0:
    #include 
    #include 
    #include 
    
    main(int argc, char **argv)
    {
      register double width;
      double sum = 0, lsum;
      register int intervals, i; 
      int nproc, iproc;
      MPI_Win sum_win;
    
      if (MPI_Init(&argc, &argv) != MPI_SUCCESS) exit(1);
      MPI_Comm_size(MPI_COMM_WORLD, &nproc);
      MPI_Comm_rank(MPI_COMM_WORLD, &iproc);
      MPI_Win_create(&sum, sizeof(sum), sizeof(sum),
                     0, MPI_COMM_WORLD, &sum_win);
      MPI_Win_fence(0, sum_win);
      intervals = atoi(argv[1]);
      width = 1.0 / intervals;
      lsum = 0;
      for (i = iproc; i < intervals; i += nproc) {
        register double x = (i + 0.5) * width;
        lsum += 4.0 / (1.0 + x * x);
      }
      lsum *= width;
      MPI_Accumulate(&lsum, 1, MPI_DOUBLE, 0, 0,
                     1, MPI_DOUBLE, MPI_SUM, sum_win);
      MPI_Win_fence(0, sum_win);
      if (iproc == 0) {
        printf("Odhad pi je %f\n", sum);
      }
      MPI_Finalize();
      return(0);
    }
    

    Je jen užitečné podotknout, že mechanismus RMA v MPI 2.0 velmi se čistě vyrovnává s problémy s odpovídajícímí datovými strukturami na různých procesorech sídlících v různých oblastech paměti. Je toho docíleno odkazem na jakési "okno", které v soubě obsahuje základní adresu, ochranu proti přístupu mimo hranice tohoto okna a dokonce také vážením adres. RMA mechanismus je tedy jakýsi podivný kříženec mezi distribuovaným sdílením paměti a zasíláním zpráv, ale na druhou stranu je to velmi čisté rozhraní, které potenciálně vytváří velmi efektivní komunikaci.

    4.3 AFAPI (Aggregate Function API)

    Na rozdíl od PVM a MPI nevznikalo AFAPI jako pokus o vybudování vrstvy pro portabilní a abstraktní rozhraní nad existujícím síťovím HW a SW, ale spíše jako velmi HW specifická knihovna pro PAPERS (Purdue's Adapter for Parallel Execution and Rapid Synchronization).
    Opět následuje příklad výpočtu pi:
    #include 
    #include 
    #include "afapi.h"
    
    main(int argc, char **argv)
    {
      register double width, sum;
      register int intervals, i;
    
      if (p_init()) exit(1);
    
      intervals = atoi(argv[1]);
      width = 1.0 / intervals;
    
      sum = 0;
      for (i = IPROC; i < intervals; i += NPROC) {
        register double x = (i + 0.5) * width;
        sum += 4.0 / (1.0 + x * x);
      }
    
      sum = p_reduceAdd64f(sum) * width;
    
      if (IPROC == CPROC) {
        printf("Odhad pi je %f\n", sum);
      }
    
      p_exit();
      return(0);
    }
    

    Z dalších podpůrných knihoven pro clustery bych jen jmenoval např. Condor (podpora migrace procesů), DFN-RPC (German Research Network - vzdálené volání procedur) nebo DQS (Distributed Queueing System - systém pro řazení úloh, který byl vyvíjen a testován pod Linuxem).

    5 Software pro clustery

    V současné době existuje široká nabídka různého programového vybavení pro clustery, od absolutně "free" programů až po komerční a drahé systémy (např. RHHAS - Red Hat High Availability Server).

    5.1 Beowulf

    Beowulf projekt začal úsilím NASA a přenáší výkon superpočítačů na Linuxové clustery. Ačkoliv Beowulf vyžaduje speciální softwarové modifikace programů pro využití clusteru, výkon, jaký nabízí pro intenzivní výpočty je opravdu ohromující.

    5.2 Evolocity

    Linux Networx Evolocity je komerční řešení. Zahrnuje HW, SW a nástroje pro správu clusteru (známé také jako ClusterWorx) pro ty, který preferují komplexní řešení.

    5.3 LifeKeeper

    Vyrábí jej firma SteelEye a jde o velmi dostupné řešení clusteru nejen pro Linux, ale také pro UNIX a Windows NT. Nabízí nástroje pro toleranci chyb a řízení zátěže.

    5.4 Linux Virtual Server

    Jde o projekt, který poskytuje běžný soubor patchů pro jádro a produktů pro správu řízení zátěže pod Linuxem. Může být použit pro vybudování škálovatelných a velmi spolehlivých clusterů.

    5.5 MOSIX

    MOSIX je řešení, které nabízí uživatelům provádět téměř všechny možné výpočty. MOSIX pracuje tak, že převezme požadavek a předá jej nejrychlejší stanici, která je právě dostupná v clusteru. Tím uživatel dostává co možná nejvyšší výkon. MOSIX dále nevyžaduje překlad SW pro přístup k jeho vymoženostem. Uživatel si vlastně ani není vědom, že jeho programy neběží lokálně.

    5.6 TurboCluster EnFuzion

    TurboCluster je obsažen v distribuci TurboLinuxu a jedná se o velice celistvý balík pro clustery. Existuje verze i pro Solaris a Win NT clustery. TurboLinux také nabízí produkt nazvaný EnFuzion pro provádění aplikací pro clustery na existujících serverech a pracovních stanicích.

    6 Piranha

    Piranha je virtuální server vyvíjený společností Red Hat. Jedná se vlastně o jádro jejich technologie pro softwarový balík "High Availability Server" a poprvé se objevila v distribucí Red Hat 6.2.

    6.1 Instalace

    Předpokládejme, že budeme konfigurovat dva stroje.

    KROK 1:
    Piranha vyžaduje jádro minimálně 2.2.14 nebo vyšší.
    KROK 2:
    Je potřeba stáhnout
    Ipvs patch do jádra a znovu přeložit jádro.
    KROK 3:
    Stáhnout si nejnovější verzi balíku Pirahna (v současné době to je 0.9.10).
    KROK 4:
    Nainstalovat piranha, piranha-docs a piranha-gui např. z RPM balíčku.

    6.2 Konfigurace

    KROK 1:
    Nejdříve je nutné nastavit heslo pro uživatele piranha pomocí passwd piranha. Také je potřeba nastavit heslo pro konfiguraci pomocí prohlížeče spuštěním htpasswd /home/httpd/html/piranha/secure/passwords piranha .
    KROK 2:
    Přidat jméno a IP adresu hostitele clusteru do /etc/hosts. Soubor na obou clusterech by měl vypadat takto:
    127.0.0.1 localhost localhost.localdomain
    10.0.0.1 cluster1 cluster1.clustersit.cz
    10.0.0.2 cluster2 cluster2.clustersit.cz 
    
    KROK 3:
    Upravit soubory /etc/hosts.allow a /root/.rhosts tak, aby umožnily přístup pro uživatele root pomocí rsh a rcp pro server i cluster.
    KROK 4:
    Nastavit Apache na obou strojích tak, aby existovaly virtuální servery http://cluster1/piranha a http://cluster2/piranha.
    KROK 5:
    Další konfigurace již probíhá pomocí prohlížeče, což umožňuje velice snadno nastavit cluster. Na primárním serveru přejděte na odkaz http://cluster1/piranha. Budete muset zadat heslo pro prohlížeč. Nejdříve klikněte na GlobalSettings a nastavte primárnímu serveru IP adresu (10.0.0.1) a stiskněte tlačítko fos, kde můžete zvolit ssh sync, pokud máte nainstalované ssh.
    KROK 6:
    Zvolte Failover a přidejte další server do clusteru. Poté změňte IP adresu, jméno, aplikační port (pro Webové služby např. 80), zařízení (eth0 nebo eth1) a timeout nové stanice. Toto se musí udělat pro obě stanice.
    KROK 7:
    Zkopírujte konfigurační soubor /etc/lvs.cf z primárního serveru na druhý stroj a na obou stanicích spusťte SW pro cluster pomocí příkazu /etc/rc.d/init.d/pulse start.

    7 Odkazy


    Obecné http://www.linux-mag.com/2000-10/clustering_04.html
    http://www.redhat.com/support/resources/howto/piranha/index.html#AEN12
    http://www.icewalkers.com/doclib/howtos/Parallel-Processing-HOWTO-3.html#ss3.3>
    PVM http://www.epm.ornl.gov/pvm/pvm_home.html
    newsgroup: comp.parallel.pvm
    MPI http://www.mcs.anl.gov:80/mpi/
    http://www-unix.mcs.anl.gov/mpi/
    newsgroup: comp.parallel.mpi
    AFARI http://garage.ecn.purdue.edu/~papers/
    Condor http://www.cs.wisc.edu/condor/
    http://www.cs.wisc.edu/condor/linux/linux.html
    email: condor-admin@cs.wisc.edu
    DFN-RPC ftp: ftp://ftp.uni-stuttgart.de/pub/rus/dfn_rpc/README_dfnrpc.html
    DQS http://www.scri.fsu.edu/~pasko/dqs.html
    http://www.genias.de/genias_welcome.html
    Beowulf http://www.beowulf.org
    Evolocity http://www.linuxnetworx.com
    LifeKeeper http://www.steeleye.com
    Linux Virtual Server http://www.linuxvirtualserver.org
    MOSIX http://www.mosix.cs.huji.ac.il
    Piranha http://www.sources.redhat.com/piranha
    http://www.redhat.com/software/advancedserver/technical/piranha.html