Rumah > pembangunan bahagian belakang > C++ > Bagaimana Mentranspose Matriks dengan Cekap dalam C ?

Bagaimana Mentranspose Matriks dengan Cekap dalam C ?

Susan Sarandon
Lepaskan: 2024-12-11 07:13:10
asal
392 orang telah melayarinya

How to Efficiently Transpose a Matrix in C  ?

Bagaimana untuk Memindahkan Matriks dengan Cepat dalam C ?

Masalah:

Pertimbangkan perkara yang besar matriks dengan elemen disusun sebagai:

a b c d e f
g h i j k l
m n o p q r 
Salin selepas log masuk

Matlamatnya ialah untuk menukar matriks ini, menghasilkan:

a g m
b h n
c I o
d j p
e k q
f l r
Salin selepas log masuk

Penyelesaian:

Untuk menukar matriks dengan cekap, pertimbangkan pendekatan berikut:

1. Transpose Naif:

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];
    }
}
Salin selepas log masuk

Kaedah mudah ini melelang melalui setiap elemen dan menyalinnya ke kedudukan terbalik. Walau bagaimanapun, ia mungkin mengalami kesilapan cache kerana corak capaian memori yang tidak dapat diramalkan.

2. Transpos untuk Pendaraban Matriks:

Apabila melakukan pendaraban matriks C = A*B, adalah berfaedah untuk transpos B. Pendekatan ini menghapuskan kesilapan cache dan mempercepatkan pengiraan dengan ketara.

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);
Salin selepas log masuk

3. Alih Sekat Menggunakan Penyekatan Gelung:

Untuk matriks besar, penyekatan gelung menawarkan prestasi yang luar biasa. Ia membahagikan matriks kepada blok yang lebih kecil dan mengubahnya secara bebas.

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);
        }
    }
}
Salin selepas log masuk

4. Transpose Menggunakan Intrinsik SSE:

Teknik lanjutan ini memanfaatkan intrinsik SSE untuk mencapai kelajuan yang tiada tandingan. Ia dengan cekap memindahkan blok 4x4 pada satu masa menggunakan satu arahan.

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);
}
Salin selepas log masuk

5. Penyekatan Gelung dengan SSE:

Menggabungkan penyekatan gelung dengan intrinsik SSE meningkatkan lagi prestasi. Pendekatan ini memproses blok 4x4 matriks dengan cekap.

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);
                }
            }
        }
    }
}
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimana Mentranspose Matriks dengan Cekap dalam C ?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan