在微博中看到有人分享了篇文章“为什么转置512×512矩阵,会比513×513矩阵慢很多?”
http://note.sdo.com/u/1557869253/n/sSPb5~k5HYUMLX0mU000QX
没仔细看原理,但与缓存的命中率有关。
今天写矩阵翻转的代码,突然想到这个问题。测了一下速度:
结论:
新建一片内存,顺序访问其中的元素,速度比较快!!!在翻转中能快个两倍左右!!!(注:我的矩阵是行优先存储的)
有关代码如下(代码不完全):
//水平翻转矩阵中的元素
void flipHorizontally(){
T tmp;
//int halfHeight=height_row/2;
int halfWidth=width_col/2;
for (int r=0; r<height_row; r++) {
for (int c=0; c<halfWidth; c++) {
int c2=width_col-1-c;
tmp=getValue(r,c);
this->operator()(r,c)=this->operator()(r,c2);
this->operator()(r,c2)=tmp;
}
}
}
//水平翻转矩阵中的元素
Matrix flipHorizontallyNewMatrix(){
Matrix flipped(height_row,width_col);
int halfWidth=width_col/2;
for (int r=0; r<height_row; r++) {
for (int c=0; c<=halfWidth; c++) {
int c2=width_col-1-c;
flipped(r,c)=this->operator()(r,c2);
flipped(r,c2)=this->operator()(r,c);
}
}
return flipped;
}
//水平翻转矩阵中的元素
Matrix flipHorizontallyNewMatrix2(){
Matrix flipped(height_row,width_col);
for (int r=0; r<height_row; r++) {
for (int c=0; c<width_col; c++) {
int c2=width_col-1-c;
flipped(r,c)=this->operator()(r,c2);
}
}
return flipped;
}
//垂直翻转矩阵中的元素
Matrix flipVerticallyNewMatrix(){
Matrix flipped(height_row,width_col);
int halfHeight=height_row/2;
for (int r=0; r<=halfHeight; r++) {
for (int c=0; c<width_col; c++) {
int r2=height_row-1-r;
flipped(r,c)=this->operator()(r2,c);
flipped(r2,c)=this->operator()(r,c);
}
}
return flipped;
}
//垂直翻转矩阵中的元素
Matrix flipVerticallyNewMatrix2(){
Matrix flipped(height_row,width_col);
for (int r=0; r<height_row; r++) {
for (int c=0; c<width_col; c++) {
int r2=height_row-1-r;
flipped(r,c)=this->operator()(r2,c);
//flipped(r2,c)=this->operator()(r,c);
}
}
return flipped;
}
//垂直翻转矩阵中的元素
void flipVertically(){
T tmp;
int halfHeight=height_row/2;
for (int r=0; r<halfHeight; r++) {
for (int c=0; c<width_col; c++) {
int r2=height_row-1-r;
tmp=getValue(r,c);
this->operator()(r,c)=this->operator()(r2,c);
this->operator()(r2,c)=tmp;
}
}
}
测试用的代码如下(代码不完全):
for (int n=10; n<1000; n+=33) {
MatrixInt m(n,n);
for (int i=0; i<m.getNumEl(); i++) {
m(i)=i;
}
int testNum=10000/n*10000/n;
Timer timer;
for(int i=0; i<testNum; i++)
m.flipVerticallyNewMatrix();
long tv1=timer.getElapsedTimeAndRestart();
for(int i=0; i<testNum; i++)
m.flipVerticallyNewMatrix2();
long tv2=timer.getElapsedTimeAndRestart();
for(int i=0; i<testNum; i++)
m.flipVertically();
long tvInplace=timer.getElapsedTimeAndRestart();
for(int i=0; i<testNum; i++)
m.flipHorizontallyNewMatrix();
long th1=timer.getElapsedTimeAndRestart();
for(int i=0; i<testNum; i++)
m.flipHorizontallyNewMatrix2();
long th2=timer.getElapsedTimeAndRestart();
for(int i=0; i<testNum; i++)
m.flipHorizontally();
long thInplace=timer.getElapsedTimeAndRestart();
cout<<"矩阵大小: "<<m.height_row<<"行*"<<m.width_col<<"列"<<endl;
cout<<"水平翻转耗时:方法1: "<<th1<<";\t\t方法2: "<<th2<<";\t\t原位翻转: "<<thInplace<<endl;
cout<<"垂直翻转耗时:方法1: "<<tv1<<";\t\t方法2: "<<tv2<<";\t\t原位翻转: "<<tvInplace<<endl;
cout<<endl;
}
测试用结果如下:
矩阵大小: 10行*10列
水平翻转耗时:方法1: 566; 方法2: 340; 原位翻转: 410
垂直翻转耗时:方法1: 652; 方法2: 342; 原位翻转: 450
矩阵大小: 43行*43列
水平翻转耗时:方法1: 364; 方法2: 180; 原位翻转: 390
垂直翻转耗时:方法1: 425; 方法2: 178; 原位翻转: 434
矩阵大小: 76行*76列
水平翻转耗时:方法1: 361; 方法2: 188; 原位翻转: 402
垂直翻转耗时:方法1: 433; 方法2: 183; 原位翻转: 445
矩阵大小: 109行*109列
水平翻转耗时:方法1: 360; 方法2: 180; 原位翻转: 397
垂直翻转耗时:方法1: 411; 方法2: 174; 原位翻转: 440
矩阵大小: 142行*142列
水平翻转耗时:方法1: 357; 方法2: 176; 原位翻转: 406
垂直翻转耗时:方法1: 413; 方法2: 173; 原位翻转: 456
矩阵大小: 175行*175列
水平翻转耗时:方法1: 353; 方法2: 173; 原位翻转: 403
垂直翻转耗时:方法1: 412; 方法2: 171; 原位翻转: 452
矩阵大小: 208行*208列
水平翻转耗时:方法1: 359; 方法2: 176; 原位翻转: 408
垂直翻转耗时:方法1: 417; 方法2: 173; 原位翻转: 455
矩阵大小: 241行*241列
水平翻转耗时:方法1: 349; 方法2: 171; 原位翻转: 400
垂直翻转耗时:方法1: 411; 方法2: 170; 原位翻转: 449
矩阵大小: 274行*274列
水平翻转耗时:方法1: 346; 方法2: 173; 原位翻转: 400
垂直翻转耗时:方法1: 406; 方法2: 167; 原位翻转: 448
矩阵大小: 307行*307列
水平翻转耗时:方法1: 343; 方法2: 170; 原位翻转: 400
垂直翻转耗时:方法1: 402; 方法2: 168; 原位翻转: 443
矩阵大小: 340行*340列
水平翻转耗时:方法1: 360; 方法2: 174; 原位翻转: 420
垂直翻转耗时:方法1: 410; 方法2: 169; 原位翻转: 447
矩阵大小: 373行*373列
水平翻转耗时:方法1: 460; 方法2: 259; 原位翻转: 398
垂直翻转耗时:方法1: 512; 方法2: 261; 原位翻转: 443
矩阵大小: 406行*406列
水平翻转耗时:方法1: 456; 方法2: 262; 原位翻转: 403
垂直翻转耗时:方法1: 516; 方法2: 255; 原位翻转: 452
矩阵大小: 439行*439列
水平翻转耗时:方法1: 450; 方法2: 248; 原位翻转: 401
垂直翻转耗时:方法1: 500; 方法2: 249; 原位翻转: 445
矩阵大小: 472行*472列
水平翻转耗时:方法1: 453; 方法2: 269; 原位翻转: 402
垂直翻转耗时:方法1: 513; 方法2: 265; 原位翻转: 450
矩阵大小: 505行*505列
水平翻转耗时:方法1: 433; 方法2: 252; 原位翻转: 390
垂直翻转耗时:方法1: 489; 方法2: 249; 原位翻转: 436
矩阵大小: 538行*538列
水平翻转耗时:方法1: 440; 方法2: 247; 原位翻转: 398
垂直翻转耗时:方法1: 497; 方法2: 247; 原位翻转: 444
矩阵大小: 571行*571列
水平翻转耗时:方法1: 443; 方法2: 256; 原位翻转: 397
垂直翻转耗时:方法1: 496; 方法2: 248; 原位翻转: 440
矩阵大小: 604行*604列
水平翻转耗时:方法1: 439; 方法2: 252; 原位翻转: 402
垂直翻转耗时:方法1: 494; 方法2: 248; 原位翻转: 438
矩阵大小: 637行*637列
水平翻转耗时:方法1: 436; 方法2: 244; 原位翻转: 397
垂直翻转耗时:方法1: 488; 方法2: 242; 原位翻转: 432
矩阵大小: 670行*670列
水平翻转耗时:方法1: 427; 方法2: 243; 原位翻转: 384
垂直翻转耗时:方法1: 483; 方法2: 238; 原位翻转: 427
矩阵大小: 703行*703列
水平翻转耗时:方法1: 449; 方法2: 257; 原位翻转: 403
垂直翻转耗时:方法1: 527; 方法2: 260; 原位翻转: 459
矩阵大小: 736行*736列
水平翻转耗时:方法1: 432; 方法2: 246; 原位翻转: 395
垂直翻转耗时:方法1: 493; 方法2: 245; 原位翻转: 440
矩阵大小: 769行*769列
水平翻转耗时:方法1: 452; 方法2: 258; 原位翻转: 409
垂直翻转耗时:方法1: 518; 方法2: 256; 原位翻转: 458
矩阵大小: 802行*802列
水平翻转耗时:方法1: 434; 方法2: 248; 原位翻转: 392
垂直翻转耗时:方法1: 492; 方法2: 248; 原位翻转: 433
矩阵大小: 835行*835列
水平翻转耗时:方法1: 415; 方法2: 240; 原位翻转: 372
垂直翻转耗时:方法1: 466; 方法2: 234; 原位翻转: 416
矩阵大小: 868行*868列
水平翻转耗时:方法1: 427; 方法2: 247; 原位翻转: 388
垂直翻转耗时:方法1: 478; 方法2: 239; 原位翻转: 433
矩阵大小: 901行*901列
水平翻转耗时:方法1: 448; 方法2: 262; 原位翻转: 400
垂直翻转耗时:方法1: 499; 方法2: 251; 原位翻转: 449
矩阵大小: 934行*934列
水平翻转耗时:方法1: 422; 方法2: 248; 原位翻转: 380
垂直翻转耗时:方法1: 477; 方法2: 237; 原位翻转: 426
矩阵大小: 967行*967列
水平翻转耗时:方法1: 436; 方法2: 257; 原位翻转: 388
垂直翻转耗时:方法1: 493; 方法2: 248; 原位翻转: 438