MPI-レイテンシ

並列計算機規格MPIのライブラリであるLAM(version7)の通信速度が気になったので、レイテンシを計測してみた。
メッセージの送受信を役割を交互に変えて、10^5回送受信を繰り返すプログラムを用いた。
経過時間とCPU利用時間を測定した。

結果は下図のようになった。


同一PC内の2CPU間では、LANケーブルを介した通信を行っていないので、 
処理が早く、CPUのほとんどをMPIのプロセスが占めている事がわかる。

異なるPCの2CPU間では、通信に時間がかかるために、
待ち時間が生じていて、その間は他のプロセスを行っている事が分かる。
普通、アルゴリズムの性能評価の指標にはCPU利用時間を用いるのだけども、
並列計算では通信の為に経過時間を指標にする必要性を確認できた。

レイテンシが他の測定結果(MPIライブラリの調査と性能の計測)よりも、
倍以上遅くなってしまっているのも気になるけれど、改善策が思い浮かばない。


測定に用いたプログラムはこちら。実行にはlamの環境が必要。

latencyMeasure.cpp

#include "mpiInterface.h"
#include "timeUtility.h"
#include <mpicxx.h>
#include <stdio.h>

int main(int argc, char** argv)
{
	
	int repeat = 100000;

	MPI::Init(argc, argv);
	
	int my_rank =  MPI::COMM_WORLD.Get_rank() ;
	
	mpiInterface inter = mpiInterface();
	
 	timeUtility time = timeUtility();
 
	for(int i=0;i<repeat * 2;i++){
		if((i + my_rank) % 2 ==0) inter.send();
		else inter.recv();
	}
	
	if(my_rank ==0){
		time.showTime();
		time.showLatency(repeat);
	}
	
	MPI::Finalize();
}

mpiInterface.cpp

#include "mpiInterface.h"
#include <mpicxx.h>
#include <iostream> 

mpiInterface::mpiInterface(){

	int my_rank = MPI::COMM_WORLD.Get_rank();

	int p = MPI::COMM_WORLD.Get_size();

	if(p!=2) cout << "error" << endl;

	int targetRank;
	if(my_rank ==0) targetRank =1;
	else targetRank = 0;
	char  sendBuf[] = "Hello";
	char recvBuf[]   = "        ";
	sendRequest =  MPI::COMM_WORLD.Send_init(sendBuf,8,MPI_CHAR,targetRank,0);
	recvRequest  = MPI::COMM_WORLD.Recv_init(recvBuf,8,MPI_CHAR,targetRank,0);

}

void mpiInterface::send(){
	sendRequest.Start();	
	sendRequest.Wait();	
}
	
void  mpiInterface::recv(){
	recvRequest.Start();
	recvRequest.Wait();
}

mpiInterface.h

#ifndef _mpiInterface_h_
#define _mpiInterface_h_

#include <mpicxx.h>

class mpiInterface{
private:
	MPI::Prequest sendRequest;
	MPI::Prequest recvRequest;
public:
	mpiInterface();
	void send();
	void recv();
};
	
#endif

timeUtility.cpp

#include "timeUtility.h"
#include <stdio.h>
#include <fstream> 
#include <sys/time.h>

timeUtility::timeUtility(){
	stime_clock  =clock();
	stime_gettimeofday = gettimeofday_sec();
}

double timeUtility::gettimeofday_sec(){
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return tv.tv_sec + (double)tv.tv_usec*1e-6;
}

void timeUtility::showTime(){
	cout <<  "Passing time is " <<   (double) (gettimeofday_sec() - stime_gettimeofday) <<endl;
	cout <<  "CPU using time is " <<  (double) (clock() - stime_clock )/CLOCKS_PER_SEC << endl;
}

void timeUtility::showLatency(int repeat){
	cout <<  "Latency(Passing time ) is " << (double) (gettimeofday_sec() - stime_gettimeofday) /repeat<< endl;
	cout <<  "Latency(CPU using time ) is " << (double) (clock() - stime_clock )/CLOCKS_PER_SEC /repeat << endl;
}

timeUtility.h

#ifndef _timeUtility_h_
#define _timeUtility_h_

#include <time.h>

class timeUtility{
private:
	clock_t stime_clock; 
	double stime_gettimeofday;
public:
	timeUtility();
	double gettimeofday_sec();
	void showTime();
	void showLatency(int);
};

#endif

書いてから思ったけども、doxygen使ったページを上げれば、良かったかな・・・