Car*_*arl 7 c++ performance cross-platform
在编码时,在性能方面要记住什么是一个好的经验法则?有无穷无尽的方法可以针对特定平台和编译器进行优化,但我正在寻找在编译器和平台上同样适用(或几乎)的答案.
act*_*.se 16
脑海中浮现出一句名言:
"我们应该忘记小的效率,比如大约97%的时间:过早的优化是所有邪恶的根源." (Knuth,Donald.结构化编程,参见陈述,ACM期刊计算调查,第6卷,第4期,1974年12月.第268页.)
但也许你不应该按价值传递大数据结构...... :-)
编辑:也许还可以避免使用O(N ^ 2)或更复杂的算法......
Jar*_*Par 12
数字#1性能提示是尽早和经常分析您的代码.有很多一般的"不要这样做"的提示,但很难保证这会影响你的应用程序的性能.为什么?每个应用程序都不同.如果你有很多元素但你的程序甚至使用了一个向量(你可能应该......),很容易说按值传递向量是不好的?
分析是了解应用程序性能的唯一方法.我遇到过很多情况,人们"优化"了代码但却没有描述过."优化"最终引入了许多错误,甚至不是代码路径中的热点.浪费每个人的时间.
编辑:
有几个人对我答案的"早期"部分发表了评论.我不认为你应该从第1天开始进行剖析.但是你也不应该等到船上1个月.
我通常首先介绍一下我有一些明确的端到端场景,或者在一个更大的项目中,一个主要功能组件.我需要一两天(通常与QA合作)将一些大型场景聚集在一起并将其抛在代码中.这是一个很好的现场检查,以及早发现明显的性能问题.在这一点上修复它们会容易一些.
在一个典型的项目中,我发现我的代码符合此标准的30%-40%通过项目(100%在客户手中).我很早就把这个时间分类了.
Joh*_*itb 11
if或switch代替通过函数指针调用.澄清:void doit(int m) { switch(m) { case 1: f1(); break; case 2: f2(); break; } }而不是void doit(void(*m)()) { m(); }可以内联调用.++t而不是t++const经常使用早期.最重要的是提高可读性.new最低限度.如果可能的话,总是更喜欢自动变量(在堆栈上)T t[N] = { };你想要零一样.operator()重载的类型).它们比通过函数指针调用更好地内联.std::vector或者std::string如果您的数量固定,则不会增长.使用boost::array<T, Size>或裸阵列并正确使用它.事实上,我几乎忘了它:
过早优化是万恶之源
Kon*_*lph 11
有人提到了函数指针(以及为什么要使用它if).好吧,甚至更好:使用仿函数,它们内联并且通常没有开销.仿函数是一个结构(或类,但通常是前者),它重载运算符(),其实例可以像普通函数一样使用:
template <typename T>
struct add {
operator T ()(T const& a, T const& b) const { return a + b; }
};
int result = add<int>()(1, 2);
Run Code Online (Sandbox Code Playgroud)
这些几乎可以在可以使用普通函数或函数指针的每个上下文中使用.他们通常从任一派生std::unary_function或std::binary_function但那往往是没有必要(实际上只做过继承了一些有用的typedefS).
编辑<int>上述代码中需要显式类型限定.类型推断仅适用于函数调用,而不适用于实例创建.但是,通常可以通过使用make辅助函数来省略它.这是在STL for pairs中完成的:
template <typename T1, typename T2>
pair<T1, T2> make_pair(T1 const& first, T2 const& second) {
return pair<T1, T2>(first, second);
}
// Implied types:
pair<int, float> pif = make_pair(1, 1.0f);
Run Code Online (Sandbox Code Playgroud)
有人在评论中提到,仿函数有时被称为"functionoids".是的杂交 -但并不完全.实际上,"functor"是"函数对象"的缩写(有些奇怪).函数在概念上是相似的,但是通过使用虚函数来实现(尽管它们有时被同义地使用).例如,一个functionoid可能看起来像这样(以及它必要的接口定义):
template <typename T, typename R>
struct UnaryFunctionoid {
virtual R invoke(T const& value) const = 0;
};
struct IsEvenFunction : UnaryFunctionoid<int, bool> {
bool invoke(int const& value) const { return value % 2 == 0; }
};
// call it, somewhat clumsily:
UnaryFunctionoid const& f = IsEvenFunction();
f.invoke(4); // true
Run Code Online (Sandbox Code Playgroud)
当然,由于其虚函数调用,这会失去仿函数所具有的任何性能优势.因此,它在不同的上下文中使用,实际上需要多态(有状态)运行时函数.
C++ FAQ 在这个主题上有更多的话要说.
在需要之前不要打扰优化.要查明是否需要,请查看个人资料.不要猜; 有证据.
此外,算法优化通常比微算法具有更大的影响.使用A-star而不是暴力寻路会更快,就像Bresenham圈子比使用sin/cos更好.当然也有例外,但它们非常(非常)罕见(<0.1%).如果您有一个好的设计,更改算法只会更改代码中的一个模块.简单.