C++ C对C++;用于简单阵列创建和i/o的代码优化
我一直在试图说服我的一个朋友避免使用动态分配的数组,并开始转向STL向量。我给他发了一些示例代码,向他展示了STL和函子/生成器可以完成的一些事情:C++ C对C++;用于简单阵列创建和i/o的代码优化,c++,optimization,compiler-construction,io,C++,Optimization,Compiler Construction,Io,我一直在试图说服我的一个朋友避免使用动态分配的数组,并开始转向STL向量。我给他发了一些示例代码,向他展示了STL和函子/生成器可以完成的一些事情: #include <iostream> #include <vector> #include <algorithm> #include <iterator> #define EVENTS 10000000 struct random_double { double operator() ()
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#define EVENTS 10000000
struct random_double {
double operator() () { return (double)rand()/RAND_MAX; }
};
int main(int argc, char **argv){
std::vector<double> vd (EVENTS);
generate(vd.begin(), vd.end(), random_double());
copy(vd.begin(), vd.end(), std::ostream_iterator<double>(std::cout, "\n"));
return 0;
}
使用g++的编译器选项是:g++-finline-funroll循环。没什么特别的。有人能告诉我为什么C++/STL版本在这种情况下会慢一些吗?瓶颈在哪里?我能否向我的朋友推销使用STL容器?在高性能情况下(如游戏),最好避免使用STL容器。是的,它们提供了出色的功能,但也带来了一些开销。这可能是灾难性的 就个人而言,我只使用std的文件处理和临时向量 但是我知道什么呢?;)
编辑:让您的朋友看一看,它试图为GPU上的计算提供类似STL的功能。几乎可以肯定的是,使用iostream库与使用printf()。如果你想给算法计时,你应该在循环之外进行输出。使用STL,特别是在使用向量和其他漂亮的实用程序类时,可能总是比使用malloc和内联函数的手动C代码慢。没有真正的解决办法 话虽如此,但性能并不是一切——并非如此。使用STL还有许多其他好处,包括:
for (std::vector<double>::iterator i = vd.begin(); i != vd.end(); ++i)
printf("%lf\n", *i);
使用的标志:
-O2-funroll循环-finline
可能会出现STL速度较慢的情况,但手动滚动多个插入/删除/查找的贴图/集将很难完成。正如尼尔指出的那样,在速度上,PrimTf从IoSover中获胜(Scott Meyers中的一个点也是更有效的C++,点23)。然而,在更复杂的系统中。能够在日志中写出完整的类是值得的。printf方法是在函数中sprintf类信息,并将其作为字符串参数传递给记录器。这样,增益会更小。我认为您甚至没有运行相同的代码。
C代码没有错误检查,并在异常时泄漏内存。
为了进行比较,你需要让C程序做C++程序所做的事情。
bool errorNumber = 0; // Need a way to pass error information back from the function
int main(int argc, char **argv)
{
......
{
vd[i]=random_double();
//
// In C++ this logic is implicit with the use of excptions.
// Any example where you don't do error checking is not valid.
// In real life any code has to have this logic built in by the developer
//
if (errorNumber != 0)
{ break;
}
}
........
free(vd); The cost of freeing the memory is not zero that needs to be factored in.
return 0;
}
相信
std::cout
的插入迭代器性能不好,我尝试插入以下functor:
struct Print {
void operator()( double d ) { printf("lf\n", d); }
};
并对stl容器上的每个使用
generate(vd.begin(), vd.end(), random_double());
//copy(vd.begin(), vd.end(), std::ostream_iterator<double>(std::cout, "\n"));
std::for_each(vd.begin(), vd.end(), Print() );
对于STL版本。。。而“原始”版本的结果大致相同
time.exe raw_vs_stl.exe raw > t.txt
real 0m 9.22s
user 0m 7.89s
sys 0m
0.67s
结论:矢量性能与原始阵列一样好。它更安全,更容易使用
(免责声明:使用VC2005)了解两种实现之间速度差异的一个技巧是深入研究程序集。组装真的没那么可怕,它向你展示了到底发生了什么。它还可以方便地查看编译器优化了什么。一般来说,汇编指令越多=越长,但请记住,某些指令比其他指令花费的时间要长得多
(我怀疑,许多其他的IDS)有一个选项来查看与相应C++行交错的程序集。(在VC,这是调试-> Windows -> DISSCOM)。< /P>嗯,C代码在初学者中有明显的内存泄漏。C++比C更受益于-O2。@ Timo:虽然在这种情况下,进程立即结束并将内存返回操作系统。修复了内存泄漏-我向我的朋友指出,这是使用STL的好处之一-更少的内存泄漏:)STL向量也是动态分配的…通常遵循大小加倍算法。STL有很多优点,但这不是其中之一。如果您必须在那里进行输出,请公平竞争并使用printf()。我不同意。在C示例中,唯一可能失败的函数是malloc和printf。如果马洛克记性不好,他可能会提出申请,但在这种极为罕见的情况下,你无论如何也无能为力。。printf在理论上可以保存文件,但在实践中永远不会。无论如何,添加错误检查与性能无关(它将执行得非常快,不会产生任何影响)。至少但不是最后一次,内存将在退出时由操作系统回收,因此free()是不必要的(而且它释放出来是C++的“错误”)。但是,同样地,在5秒钟的执行时间内只有一个free():这无关紧要。我尝试添加错误检查并运行time./c>/dev/null
,它实际上运行得更快(显然不是因为额外的代码,而是因为中断的不确定性)@Koper:你真的认为没有必要打免费电话吗?即使它在进程退出时被操作系统释放,依赖它也是非常糟糕的编码实践。一个长时间运行的程序可能会使用越来越多的内存,因为不调用free会导致泄漏。此外,并非所有操作系统都会在进程退出时回收内存,特别是那些没有虚拟内存管理器的操作系统。实时嵌入式操作系统通常不支持ha
struct Print {
void operator()( double d ) { printf("lf\n", d); }
};
generate(vd.begin(), vd.end(), random_double());
//copy(vd.begin(), vd.end(), std::ostream_iterator<double>(std::cout, "\n"));
std::for_each(vd.begin(), vd.end(), Print() );
time.exe raw_vs_stl.exe stl > t.txt
real 0m 2.48s
user 0m 1.68s
sys 0m 0.28s
time.exe raw_vs_stl.exe raw > t.txt
real 0m 9.22s
user 0m 7.89s
sys 0m