pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

在 C++ 中轉(zhuǎn)置矩陣的最快方法是什么?

What is the fastest way to transpose a matrix in C++?(在 C++ 中轉(zhuǎn)置矩陣的最快方法是什么?)
本文介紹了在 C++ 中轉(zhuǎn)置矩陣的最快方法是什么?的處理方法,對(duì)大家解決問(wèn)題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧!

問(wèn)題描述

我有一個(gè)需要轉(zhuǎn)置的矩陣(相對(duì)較大).例如假設(shè)我的矩陣是

I have a matrix (relatively big) that I need to transpose. For example assume that my matrix is

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

我希望結(jié)果如下:

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

最快的方法是什么?

推薦答案

這是個(gè)好問(wèn)題.您想要在內(nèi)存中實(shí)際轉(zhuǎn)置矩陣而不僅僅是交換坐標(biāo)的原因有很多,例如在矩陣乘法和高斯拖尾中.

This is a good question. There are many reason you would want to actually transpose the matrix in memory rather than just swap coordinates, e.g. in matrix multiplication and Gaussian smearing.

首先讓我列出我用于轉(zhuǎn)置的一個(gè)函數(shù)(請(qǐng)參閱我的答案的結(jié)尾,我找到了一個(gè)更快的解決方案)

First let me list one of the functions I use for the transpose ( please see the end of my answer where I found a much faster solution)

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];
    }
}

現(xiàn)在讓我們看看為什么轉(zhuǎn)置很有用.考慮矩陣乘法 C = A*B.我們可以這樣做.

Now let's see why the transpose is useful. Consider matrix multiplication C = A*B. We could do it this way.

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*l+j];
        }
        C[K*i + j] = tmp;
    }
}

然而,那樣的話,將會(huì)有很多緩存未命中.一個(gè)更快的解決方案是先對(duì) B 進(jìn)行轉(zhuǎn)置

That way, however, is going to have a lot of cache misses. A much faster solution is to take the transpose of B first

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);

矩陣乘法是O(n^3),轉(zhuǎn)置是O(n^2),所以轉(zhuǎn)置對(duì)計(jì)算時(shí)間的影響應(yīng)該可以忽略不計(jì)(對(duì)于大n).在矩陣乘法循環(huán)中,平鋪甚至比轉(zhuǎn)置更有效,但要復(fù)雜得多.

Matrix multiplication is O(n^3) and the transpose is O(n^2), so taking the transpose should have a negligible effect on the computation time (for large n). In matrix multiplication loop tiling is even more effective than taking the transpose but that's much more complicated.

我希望我知道一種更快的轉(zhuǎn)置方法(我找到了一個(gè)更快的解決方案,請(qǐng)參閱我的答案結(jié)尾).當(dāng) Haswell/AVX2 幾周后出來(lái)時(shí),它將具有聚集功能.我不知道這在這種情況下是否會(huì)有幫助,但我可以想象收集一列并寫(xiě)出一行.也許它會(huì)使轉(zhuǎn)置變得不必要.

I wish I knew a faster way to do the transpose ( I found a faster solution, see the end of my answer). When Haswell/AVX2 comes out in a few weeks it will have a gather function. I don't know if that will be helpful in this case but I could image gathering a column and writing out a row. Maybe it will make the transpose unnecessary.

對(duì)于高斯涂抹,您所做的是水平涂抹然后垂直涂抹.但是垂直涂抹有緩存問(wèn)題所以你要做的是

For Gaussian smearing what you do is smear horizontally and then smear vertically. But smearing vertically has the cache problem so what you do is

Smear image horizontally
transpose output 
Smear output horizontally
transpose output

這是英特爾的一篇論文解釋說(shuō)http:///software.intel.com/en-us/articles/iir-gaussian-blur-filter-implementation-using-intel-advanced-vector-extensions

Here is a paper by Intel explaining that http://software.intel.com/en-us/articles/iir-gaussian-blur-filter-implementation-using-intel-advanced-vector-extensions

最后,我在矩陣乘法(和高斯拖尾)中實(shí)際做的不是完全采用轉(zhuǎn)置,而是采用特定矢量大小(例如,SSE/AVX 為 4 或 8)的寬度的轉(zhuǎn)置.這是我使用的功能

Lastly, what I actually do in matrix multiplication (and in Gaussian smearing) is not take exactly the transpose but take the transpose in widths of a certain vector size (e.g. 4 or 8 for SSE/AVX). Here is the function I use

void reorder_matrix(const float* A, float* B, const int N, const int M, const int vec_size) {
    #pragma omp parallel for
    for(int n=0; n<M*N; n++) {
        int k = vec_size*(n/N/vec_size);
        int i = (n/vec_size)%N;
        int j = n%vec_size;
        B[n] = A[M*i + k + j];
    }
}

我嘗試了幾個(gè)函數(shù)來(lái)為大矩陣找到最快的轉(zhuǎn)置.最后,最快的結(jié)果是使用帶有 block_size=16 的循環(huán)阻塞(我找到了一個(gè)使用 SSE 和循環(huán)阻塞的更快解決方案 - 見(jiàn)下文).此代碼適用于任何 NxM 矩陣(即矩陣不必是正方形).

I tried several function to find the fastest transpose for large matrices. In the end the fastest result is to use loop blocking with block_size=16 ( I found a faster solution using SSE and loop blocking - see below). This code works for any NxM matrix (i.e. the matrix does not have to be square).

inline void transpose_scalar_block(float *A, float *B, const int lda, const int ldb, const int block_size) {
    #pragma omp parallel for
    for(int i=0; i<block_size; i++) {
        for(int j=0; j<block_size; j++) {
            B[j*ldb + i] = A[i*lda +j];
        }
    }
}

inline 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(&A[i*lda +j], &B[j*ldb + i], lda, ldb, block_size);
        }
    }
}

ldaldb 是矩陣的寬度.這些需要是塊大小的倍數(shù).查找值并為例如分配內(nèi)存一個(gè) 3000x1001 的矩陣我做這樣的事情

The values lda and ldb are the width of the matrix. These need to be multiples of the block size. To find the values and allocate the memory for e.g. a 3000x1001 matrix I do something like this

#define ROUND_UP(x, s) (((x)+((s)-1)) & -(s))
const int n = 3000;
const int m = 1001;
int lda = ROUND_UP(m, 16);
int ldb = ROUND_UP(n, 16);

float *A = (float*)_mm_malloc(sizeof(float)*lda*ldb, 64);
float *B = (float*)_mm_malloc(sizeof(float)*lda*ldb, 64);

對(duì)于 3000x1001,返回 ldb = 3008 lda = 1008

For 3000x1001 this returns ldb = 3008 and lda = 1008

我找到了一個(gè)使用 SSE 內(nèi)在函數(shù)的更快的解決方案:

I found an even faster solution using SSE intrinsics:

inline 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);
}

inline 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(&A[i2*lda +j2], &B[j2*ldb + i2], lda, ldb);
                }
            }
        }
    }
}

這篇關(guān)于在 C++ 中轉(zhuǎn)置矩陣的最快方法是什么?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

【網(wǎng)站聲明】本站部分內(nèi)容來(lái)源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問(wèn)題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請(qǐng)聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

Sorting zipped (locked) containers in C++ using boost or the STL(使用 boost 或 STL 在 C++ 中對(duì)壓縮(鎖定)容器進(jìn)行排序)
Rotating a point about another point (2D)(圍繞另一個(gè)點(diǎn)旋轉(zhuǎn)一個(gè)點(diǎn) (2D))
Image Processing: Algorithm Improvement for #39;Coca-Cola Can#39; Recognition(圖像處理:Coca-Cola Can 識(shí)別的算法改進(jìn))
How do I construct an ISO 8601 datetime in C++?(如何在 C++ 中構(gòu)建 ISO 8601 日期時(shí)間?)
Sort list using STL sort function(使用 STL 排序功能對(duì)列表進(jìn)行排序)
Is list::size() really O(n)?(list::size() 真的是 O(n) 嗎?)
主站蜘蛛池模板: 真空乳化机-灌装封尾机-首页-温州精灌| 船用烟火信号弹-CCS防汛救生圈-船用救生抛绳器(海威救生设备) | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 神超官网_焊接圆锯片_高速钢锯片_硬质合金锯片_浙江神超锯业制造有限公司 | 国际金融网_每日财经新资讯网| 航空障碍灯_高中低光强航空障碍灯_民航许可认证航空警示灯厂家-东莞市天翔航天科技有限公司 | 无缝方管|无缝矩形管|无缝方矩管|无锡方管厂家 | 法兰螺母 - 不锈钢螺母制造厂家 - 万千紧固件--螺母街 | 电镀电源整流器_高频电解电源_单脉双脉冲电源 - 东阳市旭东电子科技 | 上海网站建设-上海网站制作-上海网站设计-上海做网站公司-咏熠软件 | 北京浩云律师事务所-企业法律顾问_破产清算等公司法律服务 | 北京签证代办_签证办理_商务签证_旅游签证_寰球签证网 | 广州中央空调回收,二手中央空调回收,旧空调回收,制冷设备回收,冷气机组回收公司-广州益夫制冷设备回收公司 | 免费分销系统 — 分销商城系统_分销小程序开发 -【微商来】 | 上海三信|ph计|酸度计|电导率仪-艾科仪器 | 齿轮减速电机一体机_蜗轮蜗杆减速马达-德国BOSERL齿轮减速机带电机生产厂家 | 物和码官网,物和码,免费一物一码数字化营销SaaS平台 | 澳威全屋定制官网|极简衣柜十大品牌|衣柜加盟代理|全屋定制招商 百度爱采购运营研究社社群-店铺托管-爱采购代运营-良言多米网络公司 | B2B网站_B2B免费发布信息网站_B2B企业贸易平台 - 企资网 | 非小号行情 - 专业的区块链、数字藏品行情APP、金色财经官网 | 鑫达滑石-辽宁鑫达滑石集团 | 河南凯邦机械制造有限公司| 耐火浇注料-喷涂料-浇注料生产厂家_郑州市元领耐火材料有限公司 耐力板-PC阳光板-PC板-PC耐力板 - 嘉兴赢创实业有限公司 | 密封圈_泛塞封_格莱圈-[东莞市国昊密封圈科技有限公司]专注密封圈定制生产厂家 | 药品仓库用除湿机-变电站用防爆空调-油漆房用防爆空调-杭州特奥环保科技有限公司 | 全自动五线打端沾锡机,全自动裁线剥皮双头沾锡机,全自动尼龙扎带机-东莞市海文能机械设备有限公司 | 山东活动策划|济南活动公司|济南公关活动策划-济南锐嘉广告有限公司 | 深圳市八百通智能技术有限公司官方网站 | 365文案网_全网创意文案句子素材站| 环比机械| 电子厂招聘_工厂招聘_普工招聘_小时工招聘信息平台-众立方招工网 | 金属切削液-脱水防锈油-电火花机油-抗磨液压油-深圳市雨辰宏业科技发展有限公司 | 无锡装修装潢公司,口碑好的装饰装修公司-无锡索美装饰设计工程有限公司 | 诗词大全-古诗名句 - 古诗词赏析| 立式硫化罐-劳保用品硫化罐-厂家直销-山东鑫泰鑫硫化罐厂家 | 防渗土工膜|污水处理防渗膜|垃圾填埋场防渗膜-泰安佳路通工程材料有限公司 | 单螺旋速冻机-双螺旋-流态化-隧道式-食品速冻机厂家-广州冰泉制冷 | 媒介云-全网整合营销_成都新闻媒体发稿_软文发布平台 | 正压密封性测试仪-静态发色仪-导丝头柔软性测试仪-济南恒品机电技术有限公司 | 济南品牌包装设计公司_济南VI标志设计公司_山东锐尚文化传播 | 蓄电池在线监测系统|SF6在线监控泄露报警系统-武汉中电通电力设备有限公司 |