问题
我正在测试一个计算 Mandelbrot 分形的简单代码。我一直在检查它的性能,具体取决于检查点是否属于 Mandelbrot 集的函数中的迭代次数。-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;
}
代码:分形.h
#ifndef FRACTAL_H
#define FRACTAL_H
void fractal(int iter);
#endif
代码:分形.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
(根据评论之一)。所以解释一下:首先我只将程序编译为可执行文件,并想与我的 Lua 代码进行比较,该代码从 C 调用 isMandelbrot 函数。所以我创建了一个共享对象来从 lua 调用它 - 并且有很大的时间差异。但无法理解为什么它们随着迭代次数的增加而增长。最后发现是因为-fPIC
. 当我创建一个调用我的 lua 脚本的小 c 程序时(有效地我做同样的事情,只是不需要 .so) - 时间与 C 非常相似(没有 .so -fPIC
)。所以我在过去几天里检查了它的一些配置,它始终显示两组非常相似的结果:更快没有-fPIC
并且慢一点。