質問
マンデルブロ フラクタルを計算する簡単なコードをテストしています。点がマンデルブロ集合に属しているかどうかを確認する関数の反復回数に応じて、そのパフォーマンスを確認しています。-fPIC
驚くべきことは、フラグを追加した後、時間に大きな違いが生じていることです。私が読んだところ、オーバーヘッドは通常無視でき、私が遭遇した最高のオーバーヘッドは約 6% でした。約 30% のオーバーヘッドを測定しました。アドバイスをいただければ幸いです。
私のプロジェクトの詳細
-O3
フラグ、gcc 4.7.2、Ubuntu 12.04.2、x86_64を使用します。結果は次のようになります
#iter C (fPIC) CC/C(fPIC) 1 0.01 0.01 1.00 100 0.04 0.03 0.75 200 0.06 0.04 0.67 500 0.15 0.1 0.67 1000 0.28 0.19 0.68 2000 0.56 0.37 0.66 4000 1.11 0.72 0.65 8000 2.21 1.47 0.67 16000 4.42 2.88 0.65 32000 8.8 5.77 0.66 64000 17.6 11.53 0.66
私が使用するコマンド:
gcc -O3 -fPIC fractalMain.c fractal.c -o ffpic
gcc -O3 fractalMain.c fractal.c -o f
コード: fractalMain.c
#include <time.h>
#include <stdio.h>
#include <stdbool.h>
#include "fractal.h"
int main()
{
int iterNumber[] = {1, 100, 200, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000};
int it;
for(it = 0; it < 11; ++it)
{
clock_t start = clock();
fractal(iterNumber[it]);
clock_t end = clock();
double millis = (end - start)*1000 / CLOCKS_PER_SEC/(double)1000;
printf("Iter: %d, time: %lf \n", iterNumber[it], millis);
}
return 0;
}
コード: fractal.h
#ifndef FRACTAL_H
#define FRACTAL_H
void fractal(int iter);
#endif
コード: fractal.c
#include <stdio.h>
#include <stdbool.h>
#include "fractal.h"
void multiplyComplex(double a_re, double a_im, double b_re, double b_im, double* res_re, double* res_im)
{
*res_re = a_re*b_re - a_im*b_im;
*res_im = a_re*b_im + a_im*b_re;
}
void sqComplex(double a_re, double a_im, double* res_re, double* res_im)
{
multiplyComplex(a_re, a_im, a_re, a_im, res_re, res_im);
}
bool isInSet(double P_re, double P_im, double C_re, double C_im, int iter)
{
double zPrev_re = P_re;
double zPrev_im = P_im;
double zNext_re = 0;
double zNext_im = 0;
double* p_zNext_re = &zNext_re;
double* p_zNext_im = &zNext_im;
int i;
for(i = 1; i <= iter; ++i)
{
sqComplex(zPrev_re, zPrev_im, p_zNext_re, p_zNext_im);
zNext_re = zNext_re + C_re;
zNext_im = zNext_im + C_im;
if(zNext_re*zNext_re+zNext_im*zNext_im > 4)
{
return false;
}
zPrev_re = zNext_re;
zPrev_im = zNext_im;
}
return true;
}
bool isMandelbrot(double P_re, double P_im, int iter)
{
return isInSet(0, 0, P_re, P_im, iter);
}
void fractal(int iter)
{
int noIterations = iter;
double xMin = -1.8;
double xMax = 1.6;
double yMin = -1.3;
double yMax = 0.8;
int xDim = 512;
int yDim = 384;
double P_re, P_im;
int nop;
int x, y;
for(x = 0; x < xDim; ++x)
for(y = 0; y < yDim; ++y)
{
P_re = (double)x*(xMax-xMin)/(double)xDim+xMin;
P_im = (double)y*(yMax-yMin)/(double)yDim+yMin;
if(isMandelbrot(P_re, P_im, noIterations))
nop = x+y;
}
printf("%d", nop);
}
比較の裏話
実行可能ファイルをビルドするときにフラグを追加するのは少し人工的に見えるかもしれません-fPIC
(コメントの 1 つに従って)。説明のいくつかの言葉: 最初に、プログラムを実行可能としてコンパイルしただけで、C から isMandelbrot 関数を呼び出す Lua コードと比較したかったので、lua から呼び出す共有オブジェクトを作成しましたが、大きな時間差がありました。しかし、なぜそれらが反復回数とともに成長しているのか理解できませんでした。結局、それが原因であることがわかりました-fPIC
。lua スクリプトを呼び出す小さな C プログラムを作成する場合 (実質的に同じことを行いますが、.so は必要ありません) - 時間は C (なし-fPIC
) と非常に似ています。そのため、ここ数日間、いくつかの構成で確認しましたが、2 つの非常によく似た結果が一貫して示されています。-fPIC
そしてそれで遅くなります。