OpenMP

提供: MonoBook
ナビゲーションに移動 検索に移動

OpenMPとは、数行のおまじないを書いてコンパイルオプションを追加するだけで、 多くの処理対象に対し同じような処理をする処理を早く終わらせることができるようになる定数倍高速化ツールである。

処理に使うコンピュータの性能や使用する対象のソースコードにもよるが、 使用しない場合に比べて大体処理時間を86~22%にできる。 ただし、使用しない場合より実行中のCPU使用率が高くなる。 また、高速化効果が得られず、逆に遅くなってしまう環境もあるので注意が必要である。

使用方法

#include <stdio.h>
#include <stdlib.h>

int get_flag(unsigned char* buf,int index) {
	return (buf[index>>3] & (1<<(7-(index&7))));
}

void set_flag(unsigned char* buf,int index,int flag) {
	if(flag) {
		buf[index>>3]|=1<<(7-(index&7));
	} else {
		buf[index>>3]&=~(1<<(7-(index&7)));
	}
}

int main(int argc,char* argv[]) {
	int calc_ryo=20;
	unsigned int calc_max;
	unsigned int calc2_max;
	unsigned char* calc_buffer;
	unsigned buffer_max;
	unsigned i,j;
	if(argc>1)sscanf(argv[1],"%d",&calc_ryo);
	if(calc_ryo<0 || calc_ryo>31)calc_ryo=20;
	calc_max=1u<<calc_ryo;
	calc2_max=1u<<((calc_ryo+1)/2);
	buffer_max=calc_max>>3;
	calc_buffer=malloc(buffer_max);
	if(calc_buffer==NULL)return 1;
	printf("max: %u\n",calc_max);
	for(i=0;i<buffer_max;i++)calc_buffer[i]=0xFF;
	set_flag(calc_buffer,0,0);
	set_flag(calc_buffer,1,0);
	for(i=2;i<=calc2_max;i++) {
		if(get_flag(calc_buffer,i)) {
			#ifdef _OPENMP
			#pragma omp parallel for
			#endif
			for(j=i+i;j<calc_max;j+=i) {
				set_flag(calc_buffer,j,0);
			}
		}
	}
	free(calc_buffer);
	return 0;
}

例えばこのコードのように、多くの対象に同じような処理をしているfor文の前に

#pragma omp parallel for

というおまじないを書く。そして、

>gcc -O2 -fopenmp -o prime.exe prime.c -static

のように、コンパイルオプションに-fopenmpを追加する。

このことによりOpenMPが有効化され、実行時間が比較的短くなることが期待される。

注意点

OpenMPは、多くの対象に、互いに関係ない同じような処理をしている場合の高速化に有効である。

処理が互いに関係ある場合、例えば値の合計を取るなどの場合は、特殊な書き方が必要である。

関連項目