C++ D与C的解释++;性能差异
D中的简单示例:C++ D与C的解释++;性能差异,c++,d,C++,D,D中的简单示例: import std.stdio, std.conv, core.memory; class Foo{ int x; this(int _x){x=_x;} } void main(string args[]) { GC.disable(); int n = to!int(args[1]); Foo[] m= new Foo[n]; for(int i=0;i<n;i++){ m[i] = new Foo(i);
import std.stdio, std.conv, core.memory;
class Foo{
int x;
this(int _x){x=_x;}
}
void main(string args[]) {
GC.disable();
int n = to!int(args[1]);
Foo[] m= new Foo[n];
for(int i=0;i<n;i++){
m[i] = new Foo(i);
}
}
< C++ >(GCC)中的注解实例:运行:
为什么??这样一个简单的例子,和这么大的差别:2.54秒和0.52秒。试试这个:
import std.stdio, std.conv, core.memory;
class Foo{
int x = void;
this(in int _x){x=_x;}
}
void main(string args[]) {
GC.disable();
int n = to!int(args[1]);
Foo[] m= new Foo[n];
foreach(i; 0..n){
m[i] = new Foo(i);
}
}
您主要测量三个差异:
GC.disable()代码>,但这样做只是为了使GC不会像正常情况下那样进行收集。它不会使GC完全消失,并自动将所有内存分配重定向到C的malloc。它仍然必须做它通常做的大部分事情,以确保GC知道分配的内存以及所有需要时间的事情。通常,这是程序执行的一个相对不重要的部分(甚至忽略地面军事系统提供的好处)。然而,您的基准测试使其成为整个程序的一部分,从而夸大了这种效果
因此,我建议你考虑一下你的方法的两个变化:
或者切换到使用gdc与gcc进行比较,或者切换到dmc与dmd进行比较
使程序更加等效。要么有D和C++都在堆上分配结构,要么至少使D在不接触GC的情况下分配。如果您正在优化程序以获得最大速度,那么不管使用何种语言,您都将使用structs和C的malloc
我甚至推荐第三个改变:既然您对最高性能感兴趣,那么您应该尝试提出一个完全更好的程序。为什么不切换到结构并将它们连续地定位在内存中?这将使分配(本质上是整个计划)尽可能快
在我的机器上使用dmd和dmc运行上述代码会导致以下情况:
- DMC 8.42n(无标志):~880ms
- DMD 2.062(无标志):~1300ms
将代码修改为以下内容:
C++代码:
#include <cstdlib>
using namespace std;
class Foo{
public:
int x;
Foo(int _x);
};
Foo::Foo(int _x){
x = _x;
}
int main(int argc, char** argv) {
int n = atoi(argv[1]);
Foo** gx = new Foo*[n];
for(int i=0;i<n;i++){
gx[i] = new Foo(i);
}
return 0;
}
#include <cstdlib>
struct Foo {
int x;
};
int main(int argc, char** argv) {
int n = atoi(argv[1]);
Foo* gx = (Foo*) malloc(n * sizeof(Foo));
for(int i = 0; i < n; i++) {
gx[i].x = i;
}
free(gx);
return 0;
}
使用DMD和DMC使用我的代码会导致以下情况:
- DMC 8.42n(无标志):~95ms+-20ms
- DMD 2.062(无标志):~95ms+-20ms
本质上是相同的(我必须开始使用一些统计数据,让你更好地了解哪一个速度更快,但在这个尺度上,这是无关紧要的)。请注意,使用这种方法比单纯的方法快得多,而且D同样能够使用这种策略。在这种情况下,运行时的差异可以忽略不计,但我们保留了使用GC的好处,而且在编写D代码时可能出错的事情肯定要少得多(请注意,您的程序如何未能删除其所有分配?)
此外,如果您完全愿意,D允许您通过import std.C.stdlib使用C的标准库这将允许您真正绕过GC,并在必要时通过使用C的malloc实现最大性能。在这种情况下,这是不必要的,因此我选择了更安全、可读性更强的代码。您没有提供太多信息。例如,您甚至不显示您使用的C++程序或如何编译它。如果您没有提供必要的信息,任何人应该如何给出有用的答案?如果没有提供两个完整的程序、编译标志和编译器版本,任何性能比较都是毫无意义的。请尝试测量:void main(string args[]){GC.disable();}并从数字中减去。还要确保编译标志和优化处于一个值得尊敬的比较位置。哇,这个问题投了7票反对票?这有点极端。@GMan在编辑之前看一下原始问题。buildinforeach(i,ref foo;m){foo=new foo(i);}
会更快,因为即使在调试模式下,编译器也可以优化数组的边界检查。边界检查的开销不是可以忽略不计的吗,与内存分配相比,你的胃相当聪明。发帖后我测试了很多东西(使用emplace
之类的东西)。我正在考虑做一个编辑来展示一些结果,但它会让文章变得荒谬地长,而不会给整体结论增加太多。重点仍然是,更好的程序才是真正的解决方案(因为这两种语言的速度都快得多),而D基本上同样能够创建更好的程序。OP的程序没有让我相信在这种情况下继承和单独的堆分配是必要的。实际上,最大的区别是GCC和DMC(它将差异从400%缩小到50%左右,正如我上面的时间与OP的帖子相比所见)。但是对于剩下的部分,GC并不重要,重要的是在D中分配一个类的额外时间。当然,在基类D中还有更多的事情要做。
import std.stdio, std.conv, core.memory;
class Foo{
int x = void;
this(in int _x){x=_x;}
}
void main(string args[]) {
GC.disable();
int n = to!int(args[1]);
Foo[] m= new Foo[n];
foreach(i; 0..n){
m[i] = new Foo(i);
}
}
#include <cstdlib>
struct Foo {
int x;
};
int main(int argc, char** argv) {
int n = atoi(argv[1]);
Foo* gx = (Foo*) malloc(n * sizeof(Foo));
for(int i = 0; i < n; i++) {
gx[i].x = i;
}
free(gx);
return 0;
}
import std.conv;
struct Foo{
int x;
}
void main(string args[]) {
int n = to!int(args[1]);
Foo[] m = new Foo[](n);
foreach(i, ref e; m) {
e.x = i;
}
}