Hur kommer det sig att BLAS är optimerat?

Permalänk

Hur kommer det sig att BLAS är optimerat?

Jag har hållit på med LAPACK den sista veckan. LAPACK är ett bibliotek för olika rutiner hur man kan beräkna massa saker på det allt möjliga konstiga sättet. Men det fungerar. LAPACK är ett uråldrigt bibliotek som uppdateras fortfarande. Det är skrivet i Fortran 90, men en utgåva har översats till ANSI C. Värt att notera är att det finns mycket C-kod där som är skrivet på K&R standarden

Hur som helst. I LAPACK så finns det blas t.ex. rutinen sgemm. Denna utför matrismultiplikation.
Jag öppnade sgemm.c filen och märkte att det var mycket kod för att beräkna C = A*B

Då är frågan. Hur kan denna fil vara optimerad om det är så mycket kod? Jag testade att klistra in koden i Godbolt och jag fick fram flera tusen rader assemblerkod. Denna kan väll inte vara optimerad? Jag menar, två stycken for-satser och man har gjort en matrismultiplikation. Enligt mig i alla fall.

Permalänk
Medlem

Det är inte relevant för din fråga men det är andra gången jag ser dig skriva det. Du menar K&R.

Permalänk
Datavetare

SGEMM beräknar en av dessa

  • R ← α⋅AB+β⋅C

  • R ← α⋅ABT+β⋅C

  • R ← α⋅ATB+β⋅C

  • R ← α⋅ATBT+β⋅C

Ser det bekant ut?

FMA är något som både x86_64 och ARM64 har speciella instruktioner för, det beräknar

r ← a⋅b+c

och sedan finns Tensor-kärnor i Nvidia GPUer (och motsvarande finns även i Intel och AMD RDNA3 GPUer), dessa beräknar

R ← AB+C

Vad du länkar är ISO C version av SGEMM, den är så optimal den kan vara given begränsningarna att uttrycka vad man vill göra inom ramen av ISO C. D.v.s. inte i närheten av vad som är möjligt på en modern x86_64/ARM64 CPU!

Poängen med SGEMM och i förlängningen även övriga operationer i BLAS är att det är ett API. Man kan välja en implementationer av detta API som är långt mer optimerat än vad som är möjligt med endast ISO C. Det är "killer feature" hos BLAS.

En av de absolut mest populära användandet av hård-optimerade varianter av BLAS är via ramverk NumPy och/eller PyTorch (båda dessa har "backends" för allt från SSE, AVX, NEON på CPU till GPGPU till NPU implementationer). Finns också HW-specifika lösningar som cuBLAS.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Skrivet av Yoshman:

SGEMM beräknar en av dessa

  • R ← α⋅AB+β⋅C

  • R ← α⋅ABT+β⋅C

  • R ← α⋅ATB+β⋅C

  • R ← α⋅ATBT+β⋅C

Ser det bekant ut?

FMA är något som både x86_64 och ARM64 har speciella instruktioner för, det beräknar

r ← a⋅b+c

och sedan finns Tensor-kärnor i Nvidia GPUer (och motsvarande finns även i Intel och AMD RDNA3 GPUer), dessa beräknar

R ← AB+C

Vad du länkar är ISO C version av SGEMM, den är så optimal den kan vara given begränsningarna att uttrycka vad man vill göra inom ramen av ISO C. D.v.s. inte i närheten av vad som är möjligt på en modern x86_64/ARM64 CPU!

Poängen med SGEMM och i förlängningen även övriga operationer i BLAS är att det är ett API. Man kan välja en implementationer av detta API som är långt mer optimerat än vad som är möjligt med endast ISO C. Det är "killer feature" hos BLAS.

En av de absolut mest populära användandet av hård-optimerade varianter av BLAS är via ramverk NumPy och/eller PyTorch (båda dessa har "backends" för allt från SSE, AVX, NEON på CPU till GPGPU till NPU implementationer). Finns också HW-specifika lösningar som cuBLAS.

Intressant! Jag gillar verkligen sådant. Jag kör LAPACK som ej tar hänsyn till hårdvara, dvs ingen GPU, Nvidia eller något annat sådant flashigt. Bara ren processorkraft. Jag har inte så mycket data att beräkna, typ 5000x5000 matriser.

Just nu har jag lite problem när jag kör ssyevd. Jag får nämligen felmeddelandet On entry to SSYEVD, parameter number 8 had an illegal value, vilket betyder att 8:e argumentet i funktionen ssyevd har ett felaktigt värde. (fixat)

Så åter till tråden.
Om jag kan köra en matrismultiplikation med två stycken for-satser. Är då SGEMM snabbare, om vi endast får använda vanlig processorkraft?

Permalänk
Medlem

Det finns många implementationer av BLAS. BLAS är mer ett API/en standard än en kodbas.
Referensimplementationen är skriven i Fortran och där har mer fokus lagts på att få koden 100% korrekt än att få den så snabb som möjligt.
Det finns många andra implementationer av BLAS som är hårdoptimerade för en viss arkitektur, men koden som anropar BLAS-rutinerna behöver ju inte fundera på sådant utan kan bara använda BLAS.

Om den koden du tittar på är maskinöversatt från Fortran till C (och jag vet att det finns sådana versioner av både BLAS och LAPACK) så är den antagligen inte så väldigt optimerad.

EDIT: Efter att ha tittat på den filen du länkade till så ser jag att den mycket riktigt är maskinöversatt från FORTRAN till C med hjälp av programmet f2c.

Permalänk
Skrivet av Erik_T:

Det finns många implementationer av BLAS. BLAS är mer ett API/en standard än en kodbas.
Referensimplementationen är skriven i Fortran och där har mer fokus lagts på att få koden 100% korrekt än att få den så snabb som möjligt.
Det finns många andra implementationer av BLAS som är hårdoptimerade för en viss arkitektur, men koden som anropar BLAS-rutinerna behöver ju inte fundera på sådant utan kan bara använda BLAS.

Om den koden du tittar på är maskinöversatt från Fortran till C (och jag vet att det finns sådana versioner av både BLAS och LAPACK) så är den antagligen inte så väldigt optimerad.

EDIT: Efter att ha tittat på den filen du länkade till så ser jag att den mycket riktigt är maskinöversatt från FORTRAN till C med hjälp av programmet f2c.

Ja, det är översatt. Jag skulle aldrig tro att någon skulle skriva en sådan oläsbar kod medvetet.

LAPACK har vissa rutiner i C som man inte hittar någon annanstans. Det finns boken "Numerical Recipies in C", men den innehåller bara det mest grundläggande. Vill man ha lite mera värre saker, så måste man använda LAPACK.

Man märker att koden är gammal om den innehåller K&R-kod.

Permalänk
Medlem
Skrivet av heretic16:

Ja, det är översatt. Jag skulle aldrig tro att någon skulle skriva en sådan oläsbar kod medvetet.

LAPACK har vissa rutiner i C som man inte hittar någon annanstans. Det finns boken "Numerical Recipies in C", men den innehåller bara det mest grundläggande. Vill man ha lite mera värre saker, så måste man använda LAPACK.

Man märker att koden är gammal om den innehåller K&R-kod.

LAPACK bygger på välkända algoritmer som du kan hitta i diverse böcker om numeriska metoder eller numerisk analys. Färdig kod i just C är inte lika vanlig, men förstår man matematiken bakom så kan man ju skriva koden själv.
Eller så använder man ett bibliotek som någon annan redan skrivit - som t.ex. LAPACK.

Permalänk
Medlem

Erkänner att jag inte kan något om detta men han du möjligtvis testat att fråga ChatGPT om en bra eller bättre och kanske optimerad kod? Vore intressant om det gick.

Permalänk
Skrivet av Erik_T:

LAPACK bygger på välkända algoritmer som du kan hitta i diverse böcker om numeriska metoder eller numerisk analys. Färdig kod i just C är inte lika vanlig, men förstår man matematiken bakom så kan man ju skriva koden själv.
Eller så använder man ett bibliotek som någon annan redan skrivit - som t.ex. LAPACK.

Jag använder LAPACK.
Nu försöker jag hitta ett alternativ till att räkna ut SVD för osymmetriska matriser som är stora. Tidskrävande! Undra om jag ska använda rutinen för att beräkna egenvärden istället. Tydligen så är detta ett betydligt bättre sätt att räkna ut SVD än vanliga SVD.

function [U,S,V] = svdecon(X) % Input: % X : m x n matrix % % Output: % X = U*S*V' % % Description: % Does equivalent to svd(X,'econ') but faster % % Vipin Vijayan (2014) %X = bsxfun(@minus,X,mean(X,2)); [m,n] = size(X); if m <= n C = X*X'; [U,D] = eig(C); clear C; [d,ix] = sort(abs(diag(D)),'descend'); U = U(:,ix); if nargout > 2 V = X'*U; s = sqrt(d); V = bsxfun(@(x,c)x./c, V, s'); S = diag(s); end else C = X'*X; [V,D] = eig(C); clear C; [d,ix] = sort(abs(diag(D)),'descend'); V = V(:,ix); U = X*V; % convert evecs from X'*X to X*X'. the evals are the same. %s = sqrt(sum(U.^2,1))'; s = sqrt(d); U = bsxfun(@(x,c)x./c, U, s'); S = diag(s); end end

Nuvarande rutin är sgesvd och den är superseg. Har du ett bättre förslag, eller tycker du jag ska använda ssyevd istället?

Det tar 1163.852051 sekunder för mig att räkna ut en 5000x3000 matrix med sgesvd.

Antingen kan jag använda sgesdd som också räknar ut SVD fast på ett annat sätt. Vad tror ni är bäst för mig?
https://www.intel.com/content/www/us/en/docs/onemkl/code-samp...

Permalänk
Hedersmedlem
Skrivet av heretic16:

Om jag kan köra en matrismultiplikation med två stycken for-satser. Är då SGEMM snabbare, om vi endast får använda vanlig processorkraft?

Även om du begränsar dig till processorn vill du väl utnyttja alla finesser som den erbjuder. Om du till exempel använder MKL kommer den automatiskt använda AVX2 (eller AVX512 eller framtida varianter) om det stöds av systemet som kör programmet.

Skrivet av heretic16:

Nu försöker jag hitta ett alternativ till att räkna ut SVD för osymmetriska matriser som är stora. Tidskrävande! Undra om jag ska använda rutinen för att beräkna egenvärden istället. Tydligen så är detta ett betydligt bättre sätt att räkna ut SVD än vanliga SVD.

Är det just SVD som är målet, eller är det bara ett steg i att göra något annat?

Permalänk
Skrivet av Elgot:

Även om du begränsar dig till processorn vill du väl utnyttja alla finesser som den erbjuder. Om du till exempel använder MKL kommer den automatiskt använda AVX2 (eller AVX512 eller framtida varianter) om det stöds av systemet som kör programmet.

Är det just SVD som är målet, eller är det bara ett steg i att göra något annat?

Det är egenvektorerna som är målet. Det är PCA som är metoden. Orsaken varför PCA använder sig av SVD har med att PCA tar in en osymmetrisk matris, vilket eig i MATLAB ej kan räkna.

Men jag kommer inte köra direkt PCA, utan jag kommer köra Kernel PCA, vilket har visat sig vara en av dom bästa dimensionsreduceringsalgoritmerna då det finns valfrihet att utföra projektion samt använda olika kärnor beroende på datat.

I GNU octave så tog det 222 sekunder att göra special-SVD på en 5000x5000 matris. Jag vet inte vilken rutin EIG i GNU Octave använder.

X = randn(5000, 5000); >> tic;[U, S, V] = svdecon(X);toc Elapsed time is 222.039 seconds.

Med sgessd rutinen för en 5000x5000 matris tog det 440 sekunder. Det är självklart en förbättring jämfört med sgesvd som tog över 1000 sekunder för en 5000x3000 matris, inte ens fyrkantig!

I GNU Octave skulle jag aldrig kunna beräkna 5000x5000 matris med vanliga SVD.

Så undra om det blir bättre om man implementerar special SVD med LAPACK? Då kanske det går ännu snabbare?

Med ssyevd for en symmetrisk matris i C så kom jag till 217 sekunder för 5000x5000.

Permalänk
Hedersmedlem
Skrivet av heretic16:

I GNU octave så tog det 222 sekunder att göra special-SVD på en 5000x5000 matris. Jag vet inte vilken rutin EIG i GNU Octave använder.

X = randn(5000, 5000); >> tic;[U, S, V] = svdecon(X);toc Elapsed time is 222.039 seconds.

För mig tog Octave 949 och 136 sekunder på sig för svd och svdecon. Matlab klarar det på 25 respektive 16 sekunder, så det finns helt klart förbättringspotential.

Permalänk
Skrivet av Elgot:

För mig tog Octave 949 och 136 sekunder på sig för svd och svdecon. Matlab klarar det på 25 respektive 16 sekunder, så det finns helt klart förbättringspotential.

Jag tror inte jag ska testa special SVD i Lapack, dvs räkna ut egenvektorerna från en symmetrisk matris.
Detta har med att Lapack har stöd för att bara räkna ut U-matrisen från SVD, något som jag bara behöver.
Sedan så är multiplikation C = A*B väldigt krävande.

Jag testade jämföra sgemm, som utför C = alpha*A*B + beta*C, där alpha = 1 och beta = 0 för mig. Jämfört med två for-loopar.
sgemm visade sig kunna utföra multiplikation 150% snabbare än vanlig 2 for-satser.

Så det blir nog att hitta en svd-algoritm som passar mitt syfte.

Just nu har jag

  • sgesdd - För generella matriser - Divide & Conquer algoritm - Har visat sig snabb

  • sgesvd - För generella matriser - QR factorisering - Har visat sig seg, vet ej varför

  • ssyevd - För symmetriska matriser - Divide & Conquer - Har visat sig snabb

Sedan finns så många olika algoritmer. Vem ska man ha, vet jag inte.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Jag tror inte jag ska testa special SVD i Lapack, dvs räkna ut egenvektorerna från en symmetrisk matris.
Detta har med att Lapack har stöd för att bara räkna ut U-matrisen från SVD, något som jag bara behöver.
Sedan så är multiplikation C = A*B väldigt krävande.

Jag testade jämföra sgemm, som utför C = alpha*A*B + beta*C, där alpha = 1 och beta = 0 för mig. Jämfört med två for-loopar.
sgemm visade sig kunna utföra multiplikation 150% snabbare än vanlig 2 for-satser.

Så det blir nog att hitta en svd-algoritm som passar mitt syfte.

Just nu har jag

  • sgesdd - För generella matriser - Divide & Conquer algoritm - Har visat sig snabb

  • sgesvd - För generella matriser - QR factorisering - Har visat sig seg, vet ej varför

  • ssyevd - För symmetriska matriser - Divide & Conquer - Har visat sig snabb

Sedan finns så många olika algoritmer. Vem ska man ha, vet jag inte.

Kör du MKL? Man borde ju försöka göra som Matlab (hur det nu är).

Permalänk
Datavetare
Skrivet av Elgot:

Kör du MKL? Man borde ju försöka göra som Matlab (hur det nu är).

@heretic16 i ditt fall är nog MKL rätt svar.

Testade detta med PyTorch på CPU som använder MKL

from time import time import torch # Quick and dirty implementation of Matlab/Octave tic/toc... start = None def tic(): global start start = time() def toc(): global start elapsed = time() - start print(f'Elapsed time is {elapsed:.3f} seconds.') tic() A = torch.randn(5000, 5000) U, S, V = torch.svd(A) toc()

På en 3900X tar det

Elapsed time is 13.860 seconds.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Skrivet av Elgot:

Kör du MKL? Man borde ju försöka göra som Matlab (hur det nu är).

Jag implementerar BLAS rutiner nu. Men jag skulle behöva hjälp med att välja vilken SVD algoritm jag ska använda.

Permalänk
Skrivet av Yoshman:

@heretic16 i ditt fall är nog MKL rätt svar.

Testade detta med PyTorch på CPU som använder MKL

from time import time import torch # Quick and dirty implementation of Matlab/Octave tic/toc... start = None def tic(): global start start = time() def toc(): global start elapsed = time() - start print(f'Elapsed time is {elapsed:.3f} seconds.') tic() A = torch.randn(5000, 5000) U, S, V = torch.svd(A) toc()

På en 3900X tar det

Elapsed time is 13.860 seconds.

Snyggt!
Men jag använder LAPACK. Eller menar du att MKL finns i C kod som ej tar hänsyn till hårdvara?

Permalänk
Hedersmedlem
Skrivet av heretic16:

Snyggt!
Men jag använder LAPACK. Eller menar du att MKL finns i C kod som ej tar hänsyn till hårdvara?

Du behöver bara länka till MKL. Det är en effektiv implementation av BLAS.

Permalänk
Skrivet av Elgot:

Du behöver bara länka till MKL. Det är en effektiv implementation av BLAS.

Enligt denna sida så finns det tre typer av SVD algoritmer för generella matriser. Jag tror inte det finns någon LAPACK algoritm för symmetriska SVD matriser då symmetriska SVD matriser och symmetriska egenvärdesmatriser är samma sak.

Men det som var kul att veta är att det finns tre typer av SVD algoritmer. Två av dessa är sgesdd, sgesvd. Tydligen så är, enligt Netlib, sgesdd bättre än sgesvd, oavsett läge.

https://netlib.org/lapack/lug/node71.html

Angående MKL....är den hårdvarubaserad?
Dvs MKL är förkompilerad, så man behöver bara länka. Men denna kod som är kompilerad, har väll tagit hänsyn till en specifik hårdvara?

Permalänk
Hedersmedlem
Skrivet av heretic16:

Enligt denna sida så finns det tre typer av SVD algoritmer för generella matriser. Jag tror inte det finns någon LAPACK algoritm för symmetriska SVD matriser då symmetriska SVD matriser och symmetriska egenvärdesmatriser är samma sak.

Men det som var kul att veta är att det finns tre typer av SVD algoritmer. Två av dessa är sgesdd, sgesvd. Tydligen så är, enligt Netlib, sgesdd bättre än sgesvd, oavsett läge.

https://netlib.org/lapack/lug/node71.html

Har du symmetriska matriser (annars är väl det ett stickspår)?

Skrivet av heretic16:

Angående MKL....är den hårdvarubaserad?

Den använder bara processorn, men den försöker som sagt använda vektorinstruktioner och liknande om det finns.

Skrivet av heretic16:

Dvs MKL är förkompilerad, så man behöver bara länka. Men denna kod som är kompilerad, har väll tagit hänsyn till en specifik hårdvara?

Den har ganska generella klasser (som SSE, AVX, AVX2, AVX512 och liknande) så exakt vilken processormodell man har är inte så noga. Nya versioner av MKL kommer säkert ha stöd för framtida hårdvara också.

Permalänk
Skrivet av Elgot:

Har du symmetriska matriser (annars är väl det ett stickspår)?

Den använder bara processorn, men den försöker som sagt använda vektorinstruktioner och liknande om det finns.

Den har ganska generella klasser (som SSE, AVX, AVX2, AVX512 och liknande) så exakt vilken processormodell man har är inte så noga. Nya versioner av MKL kommer säkert ha stöd för framtida hårdvara också.

Jag försöker hålla mig till ANSI C och koden ska kunna köras på alla plattformar. Så jag får nog svälja om det går segt för mig. Men så länge det går snabbare än mitt GNU Octave. Då har jag lyckats bra.

Det finns följande algoritmer:
sgejsv, sgesdd, sgesvd, sgesvdq, sgesvdx

Dessa kan utföra SVD för generella matriser. Ryktet på nätet säger att sgesdd är alltid bättre än sgesvd. Detta håller jag med om också. Rutinen sgejsv är bara till för precision. Då finns det två algoritmer kvar, nämligen sgesvdq, sgesvdx.

Det som skiljer sgesvdq, sgesvdx från sgesdd är att sgesdd räknar både ut U, S, V, eller S endast. Medan sgesvdq och sgesvdx så har man flera valfriheter att välja vad man vill räkna ut. Jag är bara intresserad utav U matrisen i mitt PCA-fall.

https://netlib.org/lapack/explore-html/d4/dca/group__real_g_e...

Vilken algoritm bör jag använda: sgesvdq, sgesvdx ? Eller ska jag hålla mig till sgesdd?

Edit:
Glöm det! I mitt Lapack 3.2.1 så finns inte sgesvdq, sgesvdx tillgängliga.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Jag försöker hålla mig till ANSI C och koden ska kunna köras på alla plattformar. Så jag får nog svälja om det går segt för mig. Men så länge det går snabbare än mitt GNU Octave. Då har jag lyckats bra.

En lösning är väl att använda det som finns för den aktuella plattformen? CMake är ju rätt bra på att hitta bibliotek, så du kan använda MKL om det finns, annars OpenBLAS om det finns och i nödfall din egen version.

Permalänk
Skrivet av Elgot:

En lösning är väl att använda det som finns för den aktuella plattformen? CMake är ju rätt bra på att hitta bibliotek, så du kan använda MKL om det finns, annars OpenBLAS om det finns och i nödfall din egen version.

Fungerar MKL på alla hårdvaror, oavsett ålder?

Permalänk
Hedersmedlem
Skrivet av heretic16:

Fungerar MKL på alla hårdvaror, oavsett ålder?

x86 sedan lång tid tillbaka i alla fall.

Permalänk
Skrivet av Elgot:

x86 sedan lång tid tillbaka i alla fall.

Men om man inte kör x86 då? Man kanske kör AVR eller något annat mystiskt? Jag håller på med ett projekt som handlar om att porta numerisk linjär algebra till plattformsoberoende system.

Jag märker att den LAPACK kod jag använder, är mycket väl skriven på 80-talet. Vissa delar i alla fall.

Permalänk
Medlem
Skrivet av heretic16:

Men om man inte kör x86 då? Man kanske kör AVR eller något annat mystiskt? Jag håller på med ett projekt som handlar om att porta numerisk linjär algebra till plattformsoberoende system.

Då länkar du mot någon annan lämplig implementation av BLAS-rutinerna. Det är hela tanken med BLAS - att man kan skriva plattformsoberoende kod som länkas mot bibliotek med plattformsberoende kod som är optimerad för just den plattformen man kör på.

Permalänk
Skrivet av Erik_T:

Då länkar du mot någon annan lämplig implementation av BLAS-rutinerna. Det är hela tanken med BLAS - att man kan skriva plattformsoberoende kod som länkas mot bibliotek med plattformsberoende kod som är optimerad för just den plattformen man kör på.

Ja, det var detta jag ville ha svar på. BLAS och LAPACK är alltså optimerad för specifik hårdvara. I detta fall använder jag BLAS och LAPACK som är plattformsoberoende. Det är därför det går lite segt. Men med lite tur så kan jag komma snabbare än mitt GNU Octave, vilket är det primära målet.

Jag vet dock inte om mitt GNU Octave är så väl optimerat. Det gick ju segt igår att räkna ut SVD.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Men om man inte kör x86 då? Man kanske kör AVR eller något annat mystiskt? Jag håller på med ett projekt som handlar om att porta numerisk linjär algebra till plattformsoberoende system.

Då kör du ju ändå inte en version kompilerad för x86, så då har ju ju möjlighet att länka till något annat.

Skrivet av heretic16:

Jag märker att den LAPACK kod jag använder, är mycket väl skriven på 80-talet. Vissa delar i alla fall.

Ja, men det finns ju som sagt många implementationer också. API:et försöker man nog undvika att röra dock.

Skrivet av heretic16:

Ja, det var detta jag ville ha svar på. BLAS och LAPACK är alltså optimerad för specifik hårdvara. I detta fall använder jag BLAS och LAPACK som är plattformsoberoende.

Nja, du kan fortsätta använda BLAS och LAPACK, men istället för att bygga dessa själv kan du länka till implementationer som passar systemet du bygger för. MKL på x86 till exempel. Du behöver troligen inte ändra i din kod.

Permalänk
Skrivet av Elgot:

Då kör du ju ändå inte en version kompilerad för x86, så då har ju ju möjlighet att länka till något annat.
Ja, men det finns ju som sagt många implementationer också. API:et försöker man nog undvika att röra dock.
Nja, du kan fortsätta använda BLAS och LAPACK, men istället för att bygga dessa själv kan du länka till implementationer som passar systemet du bygger för. MKL på x86 till exempel. Du behöver troligen inte ändra i din kod.

@Elgot

Nu har jag hittat lite mer information.
För beräkning av PCA så fungerar sgesvd bättre än sgesdd, trots att sgesdd är snabbare om man ska ha både U, S, V. Men vill man bara ha U, så är sgesvd snabbare då man har valet att välja om man vill bara beräkna U.

Här är ett litet program som jag har gjort som beräknar PCA

>> tic; [P, W] = mi.pca(X, 2);toc The size of the matrix is 5000x5000. Do you want to apply PCA onto it? 1 = Yes, 0 = No: 1 Elapsed time is 237.496 seconds. >>

X är en 5000x5000 matris och jag vill dimensionera ned X till 2 dimensioner. Ca 240 sekunder. Rätt dåligt. Men jag tror jag använder vanliga BLAS i mitt Octave.

För sgesvd med 5000x5000 matris så tog det 256 sekunder.
För sgesdd med 5000x5000 matris så tog det 349 sekunder.

Men jag tror jag är dålig på att välja optimering.

Permalänk
Medlem
Skrivet av heretic16:

Ja, det var detta jag ville ha svar på. BLAS och LAPACK är alltså optimerad för specifik hårdvara. I detta fall använder jag BLAS och LAPACK som är plattformsoberoende.

BLAS är inte ett kodbibliotek. BLAS är en specifikation för ett kodbibliotek. Ett API om du föredrar den benämningen. Specifikationen definierar API:et för både Fortran och C.

Det finns många implementationer av BLAS. MKL innehåller en sådan implementation. Det finns många andra såsom ATLAS och OpenBLAS, eller Netlib BLAS som är referensimplementationen, skriven i FORTRAN 77 (och som inte är särskilt optimerad).

Kod som använder BLAS kan skrivas plattformsoberoende. Sedan när man bygger koden väljer man vilket BLAS bibliotek man länkar mot.

LAPACK i sin tur är ett kodbibliotek med rutiner för diverse operationer i linjär algebra. LAPACK använder sig av BLAS, så vill man att LAPACK rutiner skall köra snabbt så skall man använda en bra implementation av BLAS.
(Det finns några olika varianter av LAPACK också, men inte lika många som av BLAS eftersom det inte behövs lika ofta.)