Praca z PETSc

Kompilowanie programów

W środowisku UNIX programista ma do dyspozycji program zwany make - pozwalający na szybkie i wygodne kompilowanie programów. Ponieważ kompilator i linker z reguły wymagają ustawienia wielu opcji i podania licznych ścieżek dostępu, nie byłoby wygodnie za każdym razem podawać wszystkie potrzebne parametry wywołania kompilatora w linii komend. Do zapanowania nad tymi parametrami służy właśnie program make, a ściślej, plik Makefile, zawierający potrzebne parametry kompilacji. Skompilowanie programu sprowadza się wówczas do wydania komendy

hydra:/usr/home/bin> make moj_program

Aby jednak to działało, należy jednak napisać własny plik tekstowy nazwany Makefile w którym podane zostaną (ale tylko raz) wszystkie parametry potrzebne do kompilowania i linkowania programu. Przykładowy plik Makefile, pozwalający na skompilowanie programu z dołączeniem bibliotek PETSc podajemy poniżej. Zmienna BOPT mówi jaka wersja programu ma być tworzona. BOPT=O oznacza program zoptymalizowany, BOPT=g oznacza wersję do odpluskwiania (debuggingu). Ważne jest, żeby gotowy (tzn. odpluskwiony) program kompilować z opcją BOPT=O, gdyż to daje kilkukrotnie mniejszy (około 5 razy) i szybszy kod wynikowy. Oczywiście, aby w ogóle dało się skompilować program, muszą być ustawione zmienne środowiskowe opisane w rozdziale "Zaczynamy" . Tworzenie Makefile'ów jest odrębną sztuką. Zamiast ją zgłebiać, proponujemy pisanie własnych przez prostą modyfikację poniższego: 

Makefile

include $(PETSC_DIR)/bmake/$(PETSC_ARCH)/base
CC = gcc -DPETSC_LOG
CLINKER = gcc
CFLAGS = $(PCONF) $(PETSC_INCLUDE) $(BS_INCLUDE)
LIBBASE = libpetscsles libpetscsnes
OPTS = -O
BOPT = O

moj_program: moj_program.o
        $(CLINKER) -o moj_program moj_program.o -lm $(PETSC_LIB)

Bardziej rozbudowane Makefile, umożliwiające kompilację kilku różnych programów, znajdują się tutaj i tutaj

Uruchamianie programów

Są dwa sposoby uruchamiania programów w PETSc. Jeżeli uruchamiamy program na maszynie sekwencyjnej to wystarczy podać nazwę programu (powiedzmy, że nazywa się on moj_program) i opcje jego wywołania:

hydra:/usr/home/bin> moj_program [opcje]

Drugi sposób stosujemy, gdy uruchamiamy program na maszynie wieloprocesorowej z zainstalowaną biblioteką MPI. Wówczas program uruchamia się komendą:

hydra:/usr/home/bin> mpirun -np 4 moj_program [opcje]

Opcja -np 4 oznacza liczbę procesorów, na których będzie uruchomiony moj_program (w tym wypadku 4). Dalej podajemy nazwę programu i ewentualne opcje samego programu. 

Co jeszcze trzeba wiedzieć?

Do używania dotychczas wymienionych funkcji (działających na wektorach, macierzach i SLESie) wystarczy umieścić na początku programu następujący plik nagłówkowy:
#include "sles.h"
Zawiera on deklaracje wszystkich typów zmiennych i funkcji potrzebnych do rozwiązywania układów równań liniowych oraz innych podstawowych funkcji PETSc (np. przeglądarek, tworzenia wektorów i macierzy, itp.).

Jak już wspomnieliśmy, dzięki użyciu funkcji main() z argumentami argc, args oraz wywołaniu funkcji PetscInitialize(), tekst z linii komend zostanie przekazany bezpośrednio do programu i potraktowany jako opcje, co pozwala na sterowanie wieloma parametrami programu. Można zmieniać rozmiar zadania, podawać dodatkowe parametry itp.

W pełnym wykorzystaniu opcji pomocne będą funkcje: OptionsGetXXX(char* pre, char *name, XXX *zmienna,int *flag) gdzie w miejscu XXX wstawiamy typ wartości podawanej z linii komend: Int, Double, Scalar, String, DoubleArray. Na przykład funkcja

....
OptionsGetInt(PETSC_NULL,"-N",&rozmiar);
....
pobiera z linii komend zmienną typu int poprzedzoną symbolem -N i zapisuje w zmiennej rozmiar (której adres jest podany jako ostatni argument funkcji)

Argumenty funkcji OptionsGetXXX() mają następujące znaczenie: pierwszy to przedrostek, u nas będzie zawsze ustawiony na PETSC_NULL. Drugi to poszukiwany ciąg znaków, a trzeci argument to wskaźnik zmiennej do której będzie przekazywany wynik. Ostatni argument to wskaźnik do zmiennej, w której zapisane zostanie czy przypisanie wartości miało miejsce, czy nie. Przydatna jest też funkcja OptionsHasName(char* pre, char *name,int *flag), która sprawdza, czy dany ciąg znaków name pojawił się w linii komend i wynik zapisuje w zmiennej flag.

Ważnym ułatwieniem w pisaniu programów jest to, że wszystkie funkcje w PETSc zwracają kody błędów. Jest też makro CHKERRA(int ierr), która w przypadku wystąpienia błędu poda numer linii programu i nazwę pliku z kodem źródłowym oraz krótki opis błędu. Jeżeli zatem każdą funkcję PETSc wywołujemy następująco:

...
ierr = VecCreate(MPI_COMM_WORLD,PETSC_DECIDE,N,&v); CHKERRA(ierr);
ierr = VecSet(&val,v); CHKERRA(ierr);
...
to bardzo łatwo będziemy mogli zlokalizować i określić ewentualny błąd. W podprogramach będziemy używali analogicznego makra CHKERRQ(int ierr). W przykładowych programach przytoczonych do tej pory, nie zastosowaliśmy takiej konwencji ze względu na przejrzystość kodu źródłowego.

Przykłady

Opcje PETSc.

Standardowo PETSc zapewnia bardzo szeroką obsługę programu z linii komend. Na przykład po uruchomieniu programu z opcją -h lub -help zostanie wypisana pomoc do samego pakietu, oraz każdego komponentu PETSc dla którego była wywołana w programie funkcja [...]SetFromOptions() (Na przykład SLESSetFromOptions(sles))

Opcja -sles_view spowoduje wypisanie na konsolę informacji na temat SLESu

Opcja -vec_view po wywołaniu w programie funkcji VecAssemblyBegin(v) zostanie wypisany na konsolę wektor v. Podobna do niej -vec_view_draw narysuje w oknie graficznym wektor jako funkcję indeksu.

Opcja -mat_view po wywołaniu w programie funkcji MatAssemblyBegin(A,FINAL_ASSEMBLY) zostanie wypisana na konsolę macierz A. Podobna do niej -mat_view_draw narysuje w oknie graficznym strukturę miejsc niezerowych macierzy.

Opcja -draw_pause <n> spowoduje zatrzymanie przeglądarki graficznej (zarówno wywoływanej opcją z linii komend jak i z programu) na n sekund. Jeżeli n=0 to przeglądarka czeka na kliknięcie klawiszem myszki. To bardzo przydatna opcja, gdyż często przeglądarka jest zamykana zaraz po zakończeniu rysowania, co w wielu przypadkach nie wystarcza nawet na zauważenie, że okno pojawiło się na ekranie.

Opcją -ksp_type <typ> możemy zmienić rodzaj metody iteracyjnej używanej do rozwiązywania układu równań (szczegóły tutaj) Inne opcje będziemy omawiać na bieżąco.

Opis opcji dostępnych w każdym z programów jest wypisywany gdy uruchamiamy program z opcją help.

Opcje użytkownika.

Poniżej omówimy na przykładzie sposób łatwego przekazywania parametrów do programu w PETSc. Jeżeli w programie pojawią się linie:
#include "sles.h"
static char help[]="Pomoc";

int main(int argc,char **args)
{
 int N=5,pc_flag=0;
 double af=0.1;

 PetscInitialize(&argc,&args,PETSC_NULL,help);
 OptionsGetInt(PETSC_NULL,"-N",&N);
 OptionsGetDouble(PETSC_NULL,"-alfa",&af);
 OptionsHasName(PETSC_NULL,"-bez_pc",&pc_flag);
 PetscPrintf(MPI_COMM_WORLD,"rozmiar=%i,af=%d,pc_flag=%i\n",N,af,pc_flag);
 PetscFinalize();

 return(0)
}
to uruchomienie programu (w wersji jednoprocesorowej) z następującymi opcjami

hydra:/usr/home/bin/> program -help -N 10 -alfa 0.22

spowoduje przypisanie zmiennej rozmiar wartości 10, zmiennej af wartości 0.22, oraz zostanie wypisana pomoc do pakietu z uwzględnieniem stałej tekstowej help (patrz wyżej).

hydra:/usr/home/bin/> program -N 23 -bez_pc

spowoduje przypisanie zmiennej rozmiar wartości 23, ustawienia pc_flag na TRUE, a zmienna af pozostanie bez zmian, tzn. równa 0.1.

Ćwiczenie

  1. Wzbogać swoje dotychczasowe programy o możliwość ustawiania kluczowych parametrów z linii komend.
 
SLES, czyli rozwiązywanie układów równańliniowych Spis treści Pierwszy "poważny" program używający PETSc - rozwiązywanie równania Poissona
 

Copyright (C) Marcin Bojko i Piotr Krzyzanowski, 1998.
Ostatnia modyfikacja: 09.X.98.