Heim >Backend-Entwicklung >C++ >Wie transponiere ich eine Matrix effizient in C?
Wie transponiere ich schnell eine Matrix in C?
Problem:
Betrachten Sie eine wesentliche Matrix mit Elementen, die wie folgt angeordnet sind:
a b c d e f g h i j k l m n o p q r
Das Ziel besteht darin, diese Matrix zu transponieren, was zu einem Ergebnis führt in:
a g m b h n c I o d j p e k q f l r
Lösung:
Um die Matrix effizient zu transponieren, berücksichtigen Sie die folgenden Ansätze:
1. Naive Transponierung:
void transpose(float *src, float *dst, const int N, const int M) { #pragma omp parallel for for(int n = 0; n<n n int i="n/N;" j="n%N;" dst src><p>Diese einfache Methode durchläuft jedes Element und kopiert es an die transponierte Position. Aufgrund unvorhersehbarer Speicherzugriffsmuster kann es jedoch zu Cache-Fehlern kommen.</p> <p><strong>2. Transponieren für die Matrixmultiplikation:</strong></p> <p>Bei der Durchführung der Matrixmultiplikation C = A*B kann es vorteilhaft sein, B zu transponieren. Dieser Ansatz eliminiert Cache-Fehler und beschleunigt die Berechnung erheblich.</p> <pre class="brush:php;toolbar:false">transpose(B); for(int i=0; i<n i for j="0;" float tmp="0;" l="0;" a c transpose> <p><strong>3. Blockieren Sie die Transponierung mithilfe der Schleifenblockierung:</strong></p> <p>Bei großen Matrizen bietet die Schleifenblockierung eine außergewöhnliche Leistung. Es unterteilt die Matrix in kleinere Blöcke und transponiert diese unabhängig voneinander.</p> <pre class="brush:php;toolbar:false">void transpose_block(float *A, float *B, const int n, const int m, const int lda, const int ldb, const int block_size) { #pragma omp parallel for for(int i=0; i<n i for j="0;" transpose_scalar_block lda ldb block_size><p><strong>4. Transponieren mit SSE-Intrinsics:</strong></p> <p>Diese fortschrittliche Technik nutzt SSE-Intrinsics, um eine beispiellose Geschwindigkeit zu erreichen. Es transponiert effizient 4x4 Blöcke gleichzeitig mit einer einzigen Anweisung.</p> <pre class="brush:php;toolbar:false">void transpose4x4_SSE(float *A, float *B, const int lda, const int ldb) { __m128 row1 = _mm_load_ps(&A[0*lda]); __m128 row2 = _mm_load_ps(&A[1*lda]); __m128 row3 = _mm_load_ps(&A[2*lda]); __m128 row4 = _mm_load_ps(&A[3*lda]); _MM_TRANSPOSE4_PS(row1, row2, row3, row4); _mm_store_ps(&B[0*ldb], row1); _mm_store_ps(&B[1*ldb], row2); _mm_store_ps(&B[2*ldb], row3); _mm_store_ps(&B[3*ldb], row4); }
5. Schleifenblockierung mit SSE:
Durch die Kombination von Schleifenblockierung mit SSE-Intrinsics wird die Leistung weiter verbessert. Dieser Ansatz verarbeitet 4x4 Blöcke der Matrix effizient.
void transpose_block_SSE4x4(float *A, float *B, const int n, const int m, const int lda, const int ldb ,const int block_size) { #pragma omp parallel for for(int i=0; i<n i for j="0;" int max_i2="i+block_size" n block_size : max_j2="j+block_size" m i2="i;" j2="j;" transpose4x4_sse lda ldb></n>
Das obige ist der detaillierte Inhalt vonWie transponiere ich eine Matrix effizient in C?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!