Maison > développement back-end > C++ > Comment transposer efficacement une matrice en C ?

Comment transposer efficacement une matrice en C ?

Susan Sarandon
Libérer: 2024-12-11 07:13:10
original
346 Les gens l'ont consulté

How to Efficiently Transpose a Matrix in C  ?

Comment transposer rapidement une matrice en C ?

Problème :

Considérons un matrice avec des éléments disposés comme :

a b c d e f
g h i j k l
m n o p q r 
Copier après la connexion

Le but est de transposer cette matrice, résultant dans :

a g m
b h n
c I o
d j p
e k q
f l r
Copier après la connexion

Solution :

Pour transposer la matrice efficacement, envisagez les approches suivantes :

1. Transposition naïve :

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];
    }
}
Copier après la connexion

Cette méthode simple parcourt chaque élément et le copie dans la position transposée. Cependant, il peut souffrir de manques de cache en raison de modèles d'accès à la mémoire imprévisibles.

2. Transposer pour la multiplication matricielle :

Lors de la multiplication matricielle C = A*B, il peut être avantageux de transposer B. Cette approche élimine les échecs de cache et accélère considérablement le calcul.

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);
Copier après la connexion

3. Bloquer la transposition à l'aide du blocage de boucle :

Pour les grandes matrices, le blocage de boucle offre des performances exceptionnelles. Il divise la matrice en blocs plus petits et les transpose indépendamment.

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);
        }
    }
}
Copier après la connexion

4. Transposer à l'aide des intrinsèques SSE :

Cette technique avancée exploite les intrinsèques SSE pour atteindre une vitesse inégalée. Il transpose efficacement 4x4 blocs à la fois en utilisant une seule instruction.

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);
}
Copier après la connexion

5. Blocage de boucle avec SSE :

La combinaison du blocage de boucle avec les éléments intrinsèques SSE améliore encore les performances. Cette approche traite efficacement les blocs 4x4 de la matrice.

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);
                }
            }
        }
    }
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal