ATLAS: Przykład w C
From Centrum Komputerów Dużej Mocy, ICM Uniwersytet Warszawski
| ATLAS | |
|---|---|
| Produkt: | ATLAS |
| Producent: | środowisko open source |
| Licencja: | BSD |
| Zainstalowany na: | halo |
| Wersja: | 3.6.0 |
| Email: | pomoc@icm.edu.pl |
| Podstawowe informacje | |
| Przykład w C | |
| Przykład w Fortranie | |
Contents |
Kod
Oto przykładowy program w języku C wywołujący funkcję mnożenia macierzy przez wektor (GEMV) z biblioteki BLAS. Kod programu dostępny jest tu.
001. #include <cblas.h> 002. #include <stdio.h> 003. #include <stdlib.h> 004. 005. #define LDA 7 006. #define M 5 007. #define N 3 008. 009. void print_matrix(int m, int n, int lda, double *a) { 010. int i, j; 011. 012. for (j = 0; j < m; j++) { 013. for (i = 0; i < n; i++) 014. printf(" %5.1f", a[i+j*lda]); 015. printf("\n"); 016. } 017. } 018. 019. /* to samo co: print_matrix(m, 1, 1, x) */ 020. void print_vector(int m, double *x) { 021. int j; 022. 023. for (j = 0; j < m; j++) 024. printf(" %5.1f\n", x[j]); 025. } 026. 027. int main() { 028. double a[M][LDA], x[N], y[M]; 029. double alpha = 0.5; 030. double beta = 0.0; 031. 032. int i, j; 033. 034. /* zerowanie tablicy a */ 035. for (j = 0; j < M; j++) 036. for (i = 0; i < N; i++) 037. a[j][i] = 0.0; 038. 039. /* inicjalizacja tablicy a */ 040. a[0][0] = 1.0; 041. a[0][1] = -2.0; 042. a[1][1] = 3.0; 043. a[2][2] = -0.5; 044. a[3][1] = 0.5; 045. a[4][0] = 1.0; 046. a[4][1] = -1.0; 047. 048. /* inicjalizacja wektora x */ 049. x[0] = 10.0; 050. x[1] = 20.0; 051. x[2] = 30.0; 052. 053. printf("Macierz A:\n"); 054. print_matrix(M, N, LDA, (double *)a); 055. 056. printf("\n"); 057. printf("Wektor X:\n"); 058. print_vector(N, x); 059. 060. /* y := alpha*a*x + beta*y */ 061. cblas_dgemv(CblasRowMajor, CblasNoTrans, M, N, alpha, (double *)a, LDA, x, 1, beta, y, 1); 062. 063. printf("\n"); 064. printf("Wektor Y (=A*X):\n"); 065. print_vector(M, y); 066. 067. return 0; 068. }
Kompilacja i linkowanie
Na klastrze halo, używając kompilatorów GNU, program kompilujemy i linkujemy następująco (korzystamy z 64-bitowej wersji biblioteki ATLAS):
gcc -c -o testatlas.o -I/opt/atlas/64/include testatlas.c gcc -o testatlas.x testatlas.o -L/opt/atlas/64/lib -lcblas -lf77blas -latlas -lf2c
Jeśli używamy kompilatorów Portland Group, wydajemy następujące polecenia (również korzystając z 64-bitowej wersji ATLASa):
use_pgi pgcc -c -o testatlas.o -I/opt/atlas/64/include testatlas.c pgcc -o testatlas.x testatlas.o -L/opt/atlas/64/lib -lcblas -lf77blas -latlas -lf2c
Uwaga: zarówno w przypadku kompilatorów GNU, jak i Portland Group, zmiana kolejności argumentów podawanych w czasie linkowania (drugie polecenie) może spowodować błąd. Należy dbać o to aby nie zmieniać kolejności bibliotek wewnątrz zaznaczonego na czerwono fragmentu, oraz aby pliki obiektowe znajdowały się przed tym fragmentem.
Komentarz do programu
Linia 001: plik nagłówkowy dla funkcji BLAS.
Linie 005-007: stałe opisujące wielkość macierzy i wektorów.
Linie 009-025: pomocnicze funkcje służące do wypisywania zawartości macierzy i wektorów.
Linia 028: definicja macierzy A i wektorów X, Y.
Deklarujemy macierz A o rozmiarach 5x7,
choć korzystać będziemy jedynie z fragmentu tej pamięci: podmacierzy 5x3.
Ponadto deklarujemy wektor X o rozmiarze 3 oraz wektor Y o rozmiarze 5.
Zauważmy, że wszędzie używamy liczb zmiennoprzecinkowych podwójnej precyzji (double).
Linie 029-030: stałe używane w funkcji GEMV (patrz linia 061).
Linie 034-051: inicjalizacja macierzy A i wektora X.
Linie 053-058: wypisanie danych wejściowych (macierzy A i wektora X).
Linia 061: wywołujemy funkcję DGEMV z bibioteki BLAS liczącą y: = αAx + βy.
Przedrostek D w nazwie funkcji oznacza, że używamy liczb zmiennoprzecinkowych podwójnej precyzji (double).
Ponieważ w linii 030 ustawiliśmy β = 0, to nie musieliśmy inicjalizować wektora Y.
Linie 063-065: wypisanie wyniku (wektora Y).
Wynik działania
Macierz A:
1.0 -2.0 0.0
0.0 3.0 0.0
0.0 0.0 -0.5
0.0 0.5 0.0
1.0 -1.0 0.0
Wektor X:
10.0
20.0
30.0
Wektor Y (=A*X):
-15.0
30.0
-7.5
5.0
-5.0
