# Welcome to Chipset's homepage!

## 测试配置

• 硬件: Intel Core i7 920@2.67Ghz(4 core, HyperThread), 12GB RAM
• 操作系统: Microsoft Windows 7 64-bit
 测试名称 编译器/解译器 编译/运行选项 VC++ Visual C++ 2008 (32-bit) /Ox /Ob2 /Oi /Ot /GL /FD /MD /GS- /Gy /arch:SSE /fp:fast VC++_OpenMP Visual C++ 2008 (32-bit) /Ox /Ob2 /Oi /Ot /GL /FD /MD /GS- /Gy /arch:SSE /fp:fast /openmp IC++ Intel C++ Compiler (32-bit) /Ox /Og /Ob2 /Oi /Ot /Qipo /GA /MD /GS- /Gy /arch:SSE2 /fp:fast /Zi /QxHost IC++_OpenMP Intel C++ Compiler (32-bit) /Ox /Og /Ob2 /Oi /Ot /Qipo /GA /MD /GS- /Gy /arch:SSE2 /fp:fast /Zi /QxHost /Qopenmp GCC GCC 4.3.4 in Cygwin (32-bit) -O3 -march=native -ffast-math GCC_OpenMP GCC 4.3.4 in Cygwin (32-bit) -O3 -march=native -ffast-math -fopenmp C++/CLI Visual C++ 2008 (32-bit), .Net Framework 3.5 /Ox /Ob2 /Oi /Ot /GL /FD /MD /GS- /fp:fast /Zi /clr /TP C++/CLI_OpenMP Visual C++ 2008 (32-bit), .Net Framework 3.5 /Ox /Ob2 /Oi /Ot /GL /FD /MD /GS- /fp:fast /Zi /clr /TP /openmp C# Visual C# 2008 (32-bit), .Net Framework 3.5 *C#_outref Visual C# 2008 (32-bit), .Net Framework 3.5 F# F# 2.0 (32-bit), .Net Framework 3.5 Java Java SE 1.6.0_17 -server JsChrome Chrome 5.0.375.86 JsFirefox Firefox 3.6 LuaJIT LuaJIT 2.0.0-beta4 (32-bit) Lua LuaJIT (32-bit) -joff Python Python 3.1.2 (32-bit) *IronPython IronPython 2.6 for .Net 4 *Jython Jython 2.5.1 Ruby Ruby 1.9.1p378

## 结果及分析

 Test Time(sec) Relative time IC++_OpenMP 2.861 0.19x VC++_OpenMP 3.140 0.21x GCC_OpenMP 3.359 0.23x C++/CLI_OpenMP 5.147 0.35x IC++ 14.761 1.00x VC++ 17.632 1.19x GCC 19.500 1.32x C++/CLI 27.634 1.87x Java 30.527 2.07x C#_outref 44.220 3.00x F# 47.172 3.20x C# 48.194 3.26x JsChrome 237.880 16.12x LuaJIT 829.777 56.21x Lua 1,227.656 83.17x IronPython 2,921.573 197.93x JsFirefox 3,588.778 243.13x Python 3,920.556 265.60x Jython 6,211.550 420.81x Ruby 77,859.653 5,274.69x

### C++/.Net/Java组别

C++.Net的测试结果和上一篇博文相若，而C#F#无显著区别。但是，C++/CLI虽然同样产生IL，于括管的.Net平台上执行，其渲染时间 却只是C#/F#55%左右。为什么呢？使用ildasm去反汇编C++/CLIC#的可执行文件后，可以发现，程序的热点函数 Sphere.Intersect()在两个版本中，C++/CLI版本的代码大小(code size)201字节， C#则为125字节！ C++/CLI版本在编译时，已把函数内所有Vec类的方法调用全部内联，而C#版本则使用callvirt调用Vec的方法。估计JIT没有把这函数进 行内联，做成这个性能差异。另外，C++/CLI版本使用了值类型，并使用指针(代码中为引用)托管代码(C++/CLI)的渲染时间，仅为原生非括管代码(IC++)1.91倍，个人觉得.NetJIT已经非常不错。

C++方面，Intel C++编译器最快，Visual C++慢一点点(1.19x)GCC再慢一点点(1.32x)。这结果符合本人预期。 Intel C++OpenMP版本和单线程比较，达5.16加速比(speedup)，对于4Hyper Threading来说算是不错的结果。读者若有兴趣，也可以自行测试C# 4.0的并行新特性。

### 动态语言组别

posted on 2010-12-02 13:23 Chipset 阅读(2742) 评论(4)  编辑 收藏 引用 所属分类: 消遣转载 ### Feedback

#### #re: C++/C#/F#/Java/JS/Lua/Python/Ruby渲染速度比试 2010-12-02 14:03 Chipset

#include <math.h> // smallpt, a Path Tracer by Kevin Beason, 2008
#include <stdlib.h> // Make : g++ -O3 -fopenmp smallpt.cpp -o smallpt
#include <stdio.h> // Remove "-fopenmp" for g++ version < 4.2
#include <time.h> // MILO
#include "erand48.inc" // MILO
#define M_PI 3.141592653589793238462643 // MILO
struct Vec { // Usage: time ./smallpt 5000 && xv image.ppm
double x, y, z; // position, also color (r,g,b)
Vec(double x_=0, double y_=0, double z_=0){ x=x_; y=y_; z=z_; }
Vec operator+(const Vec &b) const { return Vec(x+b.x,y+b.y,z+b.z); }
Vec operator-(const Vec &b) const { return Vec(x-b.x,y-b.y,z-b.z); }
Vec operator*(double b) const { return Vec(x*b,y*b,z*b); }
Vec mult(const Vec &b) const { return Vec(x*b.x,y*b.y,z*b.z); }
Vec& norm(){ return *this = *this * (1/sqrt(x*x+y*y+z*z)); }
double dot(const Vec &b) const { return x*b.x+y*b.y+z*b.z; } // cross:
Vec operator%(const Vec &b){return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);}
};
struct Ray { Vec o, d; Ray(const Vec &o_, const Vec &d_) : o(o_), d(d_) {} };
enum Refl_t { DIFF, SPEC, REFR }; // material types, used in radiance()
struct Sphere {
double rad; // radius
Vec p, e, c; // position, emission, color
Refl_t refl; // reflection type (DIFFuse, SPECular, REFRactive)
Sphere(double rad_, Vec p_, Vec e_, Vec c_, Refl_t refl_):
rad(rad_), p(p_), e(e_), c(c_), refl(refl_) {}
double intersect(const Ray &r) const { // returns distance, 0 if nohit
Vec op = p-r.o; // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0
double t, eps=1e-4, b=op.dot(r.d), det=b*b-op.dot(op)+rad*rad;
if (det<0) return 0; else det=sqrt(det);
return (t=b-det)>eps ? t : ((t=b+det)>eps ? t : 0);
}
};
Sphere spheres[] = {//Scene: radius, position, emission, color, material
Sphere(1e5, Vec( 1e5+1,40.8,81.6), Vec(),Vec(.75,.25,.25),DIFF),//Left
Sphere(1e5, Vec(-1e5+99,40.8,81.6),Vec(),Vec(.25,.25,.75),DIFF),//Rght
Sphere(1e5, Vec(50,40.8, 1e5), Vec(),Vec(.75,.75,.75),DIFF),//Back
Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(), DIFF),//Frnt
Sphere(1e5, Vec(50, 1e5, 81.6), Vec(),Vec(.75,.75,.75),DIFF),//Botm
Sphere(1e5, Vec(50,-1e5+81.6,81.6),Vec(),Vec(.75,.75,.75),DIFF),//Top
Sphere(16.5,Vec(27,16.5,47), Vec(),Vec(1,1,1)*.999, SPEC),//Mirr
Sphere(16.5,Vec(73,16.5,78), Vec(),Vec(1,1,1)*.999, REFR),//Glas
Sphere(600, Vec(50,681.6-.27,81.6),Vec(12,12,12), Vec(), DIFF) //Lite
};
inline double clamp(double x){ return x<0 ? 0 : x>1 ? 1 : x; }
inline int toInt(double x){ return int(pow(clamp(x),1/2.2)*255+.5); }
inline bool intersect(const Ray &r, double &t, int &id){
double n=sizeof(spheres)/sizeof(Sphere), d, inf=t=1e20;
for(int i=int(n);i--;) if((d=spheres[i].intersect(r))&&d<t){t=d;id=i;}
return t<inf;
}
Vec radiance(const Ray &r, int depth, unsigned short *Xi){
double t; // distance to intersection
int id=0; // id of intersected object
if (!intersect(r, t, id)) return Vec(); // if miss, return black
const Sphere &obj = spheres[id]; // the hit object
Vec x=r.o+r.d*t, n=(x-obj.p).norm(), nl=n.dot(r.d)<0?n:n*-1, f=obj.c;
double p = f.x>f.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl
if (++depth>5) if (erand48(Xi)<p) f=f*(1/p); else return obj.e; //R.R.
if (depth > 100) return obj.e; // MILO
if (obj.refl == DIFF){ // Ideal DIFFUSE reflection
double r1=2*M_PI*erand48(Xi), r2=erand48(Xi), r2s=sqrt(r2);
Vec w=nl, u=((fabs(w.x)>.1?Vec(0,1):Vec(1))%w).norm(), v=w%u;
Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm();
return obj.e + f.mult(radiance(Ray(x,d),depth,Xi));
} else if (obj.refl == SPEC) // Ideal SPECULAR reflection
return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi));
Ray reflRay(x, r.d-n*2*n.dot(r.d)); // Ideal dielectric REFRACTION
bool into = n.dot(nl)>0; // Ray from outside going in?
double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t;
if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) // Total internal reflection
return obj.e + f.mult(radiance(reflRay,depth,Xi));
Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm();
double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n));
double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P);
return obj.e + f.mult(depth>2 ? (erand48(Xi)<P ? // Russian roulette
radiance(reflRay,depth,Xi)*RP:radiance(Ray(x,tdir),depth,Xi)*TP) :
radiance(reflRay,depth,Xi)*Re+radiance(Ray(x,tdir),depth,Xi)*Tr);
}
int main(int argc, char *argv[]){
clock_t start = clock(); // MILO
int w=512, h=512, samps = argc==2 ? atoi(argv)/4 : 250; // # samples
Ray cam(Vec(50,52,295.6), Vec(0,-0.042612,-1).norm()); // cam pos, dir
Vec cx=Vec(w*.5135/h), cy=(cx%cam.d).norm()*.5135, r, *c=new Vec[w*h];
#pragma omp parallel for schedule(dynamic, 1) private(r) // OpenMP
for (int y=0; y<h; y++){ // Loop over image rows
fprintf(stderr,"\rRendering (%d spp) %5.2f%%",samps*4,100.*y/(h-1));
unsigned short Xi={0,0,y*y*y}; // MILO
for (unsigned short x=0; x<w; x++) // Loop cols
for (int sy=0, i=(h-y-1)*w+x; sy<2; sy++) // 2x2 subpixel rows
for (int sx=0; sx<2; sx++, r=Vec()){ // 2x2 subpixel cols
for (int s=0; s<samps; s++){
double r1=2*erand48(Xi), dx=r1<1 ? sqrt(r1)-1: 1-sqrt(2-r1);
double r2=2*erand48(Xi), dy=r2<1 ? sqrt(r2)-1: 1-sqrt(2-r2);
Vec d = cx*( ( (sx+.5 + dx)/2 + x)/w - .5) +
cy*( ( (sy+.5 + dy)/2 + y)/h - .5) + cam.d;
r = r + radiance(Ray(cam.o+d*140,d.norm()),0,Xi)*(1./samps);
} // Camera rays are pushed ^^^^^ forward to start in interior
c[i] = c[i] + Vec(clamp(r.x),clamp(r.y),clamp(r.z))*.25;
}
}
printf("\n%f sec\n", (float)(clock() - start)/CLOCKS_PER_SEC); // MILO
FILE *f = fopen("image.ppm", "w"); // Write image to PPM file.
fprintf(f, "P3\n%d %d\n%d\n", w, h, 255);
for (int i=0; i<w*h; i++)
fprintf(f,"%d %d %d ", toInt(c[i].x), toInt(c[i].y), toInt(c[i].z));
}
回复  更多评论

#### #re: C++/C#/F#/Java/JS/Lua/Python/Ruby渲染速度比试 2013-09-20 21:03 冰水

ruby整数运算也就慢30倍左右。

#### #re: C++/C#/F#/Java/JS/Lua/Python/Ruby渲染速度比试 2015-01-23 10:20 路过

 只有注册用户登录后才能发表评论。 【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库 相关文章:
{"ft_lang_label":"__label__zh","ft_lang_prob":0.6977191,"math_prob":0.9927354,"size":3768,"snap":"2019-35-2019-39","text_gpt3_token_len":2440,"char_repetition_ratio":0.10706695,"word_repetition_ratio":0.27251732,"special_character_ratio":0.40658173,"punctuation_ratio":0.16759002,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.99764824,"pos_list":[0,1,2],"im_url_duplicate_count":[null,2,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2019-08-21T05:35:03Z\",\"WARC-Record-ID\":\"<urn:uuid:dbf401a8-2901-469c-a2c4-0d9794f47fa3>\",\"Content-Length\":\"89676\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:b31e431a-0167-4559-bcd0-196b839f6675>\",\"WARC-Concurrent-To\":\"<urn:uuid:89252f8d-83fb-4d1f-8531-bfbe334450a6>\",\"WARC-IP-Address\":\"47.97.166.246\",\"WARC-Target-URI\":\"http://www.cppblog.com/Chipset/archive/2010/12/02/135260.html\",\"WARC-Payload-Digest\":\"sha1:33IC62J53KRWZRNDRSPSXH4T2A4EHSH3\",\"WARC-Block-Digest\":\"sha1:GGXS666DZO23XYSFVYLVP337JTKASUJT\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2019/CC-MAIN-2019-35/CC-MAIN-2019-35_segments_1566027315809.69_warc_CC-MAIN-20190821043107-20190821065107-00100.warc.gz\"}"}