私は C++ プログラミングの初心者です。すべての MatLab ソフトウェアを C++ に移行することによる利点を確認しようとしています。私は主に非線形の有限要素処理を行っているため、大規模に実行する必要がある操作の 1 つは、2 つのベクトルの外積です。Matlab と C++ で 2 つの実装をテストしましたが、C++ の方がはるかに高速なようです。C++ では、2 つの異なる実装が異なるタイミングを提供します。インテル MKL を使用しています。
コードは次のとおりです。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <mkl.h>
void vprod( double vgr[3], double vg1[3], double vg2[3]);
int main() {
double v1[3]={1.22, 2.65, 3.65}, v2[3]={6.98, 98.159, 54.65}, vr[3];
int LC=1000000;
int i,j,k;
double tiempo=0.0, tinicial;
//------------------------------------------------------------------------
std::cout << "INLINE METHOD: " << std::endl;
tinicial = dsecnd();
for (i=0; i<LC; i++){
vr[0] = v1[1]*v2[2]-v1[2]*v2[1];
vr[1] =-(v1[0]*v2[2]-v1[2]*v2[0]);
vr[2] = v1[0]*v2[1]-v1[1]*v2[0];
};
tiempo = (dsecnd() - tinicial);
std::cout << "Tiempo Total: " << tiempo << std::endl;
std::cout << "Resultado: " << vr[0] << std::endl;
//------------------------------------------------------------------------
//------------------------------------------------------------------------
std::cout << "FUNCTION METHOD: " << std::endl;
tinicial = dsecnd();
for (i=0; i<LC; i++){
vprod (vr,v1,v2);
};
tiempo = (dsecnd() - tinicial);
std::cout << "Tiempo Total: " << tiempo << std::endl;
std::cout << "Resultado: " << vr[0] << std::endl;
//------------------------------------------------------------------------
std::cin.ignore();
return 0;
}
inline void vprod( double vgr[3], double vg1[3], double vg2[3]){
vgr[0] = vg1[1]*vg2[2]-vg1[2]*vg2[1];
vgr[1] =-(vg1[0]*vg2[2]-vg1[2]*vg2[0]);
vgr[2] = vg1[0]*vg2[1]-vg1[1]*vg2[0];
}
私の質問は: なぜ最初の実装が 2 番目の実装よりも 3 倍高速なのですか? これは関数呼び出しのオーバーヘッドの結果ですか? ありがとう !!!
編集:コンパイラが定数ベクトルを使用したループの結果を「推測」するのを避けるために、コードを変更しました。@phonetagger が示したように、結果は大きく異なります。vprod 関数を使用せずに 28500 マイクロ秒、vprod
関数を使用して 29000 マイクロ秒を得ました。この数値は、Ox 最適化を使用して取得されました。inline キーワードがオンの場合、最適化を変更しても比較には影響しませんが、数値は少し上がります。また、inline キーワードが使用されていない (最適化がオフになっている) 場合、タイミングは vprod 関数を使用しない場合は 32000、関数を使用する場合は 37000 です。そのため、関数呼び出しのオーバーヘッドは約 5000 マイクロ秒になる可能性があります。
新しいコードは次のとおりです。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <mkl.h>
//#include <mkl_lapack.h>
void vprod( double *vgr, int ploc, double *vg1, double *vg2);
int main() {
int nv=1000000;
int dim=3*nv;
double *v1, *v2, *vr; // Declare Pointers
int ploc, i;
double tiempo=0.0, tinicial;
v1 = new double [dim]; //Allocate block of memory
v2 = new double [dim];
vr = new double [dim];
// Fill vectors with something
for (i = 0; i < dim; i++) {
v1[i] =1.25 + (double)(i+1);
v2[i] =2.62+ 2*(double)(i+7);
}
//------------------------------------------------------------------------
std::cout << "RUTINA CON CODIGO INLINE: \n" ;
tinicial = dsecnd();
ploc = 0; // ploc points to an intermediate location.
for (i=0; i<nv; i++){
vr[ploc] = v1[ploc+1]*v2[ploc+2]-v1[ploc+2]*v2[ploc+1];
vr[ploc+1] =-(v1[ploc]*v2[ploc+2]-v1[ploc+2]*v2[ploc]);
vr[ploc+2] = v1[ploc]*v2[ploc+1]-v1[ploc+1]*v2[ploc];
ploc +=3;
};
tiempo = (dsecnd() - tinicial);
std::cout << "Tiempo Total: " << tiempo << ".\n";
std::cout << "Resultado: " << vr[0] << ".\n";
delete v1,v2,vr;
v1 = new double [dim]; //Allocate block of memory
v2 = new double [dim];
vr = new double [dim];
//------------------------------------------------------------------------
//------------------------------------------------------------------------
std::cout << "RUTINA LLAMANDO A FUNCION: \n" ;
ploc=0;
tinicial = dsecnd();
for (i=0; i<nv; i++){
vprod ( vr, ploc, v1, v2);
ploc +=3;
};
tiempo = (dsecnd() - tinicial);
std::cout << "Tiempo Total: " << tiempo << ".\n";
std::cout << "Resultado: " << vr[0] << ".\n";
//------------------------------------------------------------------------
std::cin.ignore();
return 0;
}
inline void vprod( double *vgr, int ploc, double *vg1, double *vg2) {
vgr[ploc] = vg1[ploc+1]*vg2[ploc+2]-vg1[ploc+2]*vg2[ploc+1];
vgr[ploc+1] = -(vg1[ploc]*vg2[ploc+2]-vg1[ploc+2]*vg2[ploc]);
vgr[ploc+2] = vg1[ploc]*vg2[ploc+1]-vg1[ploc+1]*vg2[ploc];
}