Heim >Backend-Entwicklung >C++ >Wie transponiere ich eine Matrix effizient in C?

Wie transponiere ich eine Matrix effizient in C?

Susan Sarandon
Susan SarandonOriginal
2024-12-11 07:13:10319Durchsuche

How to Efficiently Transpose a Matrix 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*M; n++) {
        int i = n/N;
        int j = n%N;
        dst[n] = src[M*j + i];
    }
}

Diese einfache Methode durchläuft jedes Element und kopiert es an die transponierte Position. Aufgrund unvorhersehbarer Speicherzugriffsmuster kann es jedoch zu Cache-Fehlern kommen.

2. Transponieren für die Matrixmultiplikation:

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.

transpose(B);
for(int i=0; i<N; i++) {
    for(int j=0; j<K; j++) {
        float tmp = 0;
        for(int l=0; l<M; l++) {
            tmp += A[M*i+l]*B[K*j+l];
        }
        C[K*i + j] = tmp;
    }
}
transpose(B);

3. Blockieren Sie die Transponierung mithilfe der Schleifenblockierung:

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.

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+=block_size) {
        for(int j=0; j<m; j+=block_size) {
            transpose_scalar_block(&amp;A[i*lda +j], &amp;B[j*ldb + i], lda, ldb, block_size);
        }
    }
}

4. Transponieren mit SSE-Intrinsics:

Diese fortschrittliche Technik nutzt SSE-Intrinsics, um eine beispiellose Geschwindigkeit zu erreichen. Es transponiert effizient 4x4 Blöcke gleichzeitig mit einer einzigen Anweisung.

void transpose4x4_SSE(float *A, float *B, const int lda, const int ldb) {
    __m128 row1 = _mm_load_ps(&amp;A[0*lda]);
    __m128 row2 = _mm_load_ps(&amp;A[1*lda]);
    __m128 row3 = _mm_load_ps(&amp;A[2*lda]);
    __m128 row4 = _mm_load_ps(&amp;A[3*lda]);
     _MM_TRANSPOSE4_PS(row1, row2, row3, row4);
     _mm_store_ps(&amp;B[0*ldb], row1);
     _mm_store_ps(&amp;B[1*ldb], row2);
     _mm_store_ps(&amp;B[2*ldb], row3);
     _mm_store_ps(&amp;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+=block_size) {
        for(int j=0; j<m; j+=block_size) {
            int max_i2 = i+block_size < n ? i + block_size : n;
            int max_j2 = j+block_size < m ? j + block_size : m;
            for(int i2=i; i2<max_i2; i2+=4) {
                for(int j2=j; j2<max_j2; j2+=4) {
                    transpose4x4_SSE(&amp;A[i2*lda +j2], &amp;B[j2*ldb + i2], lda, ldb);
                }
            }
        }
    }
}

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn