相关疑难解决方法(0)

什么时候优化过早?

正如Knuth所说,

我们应该忘记小的效率,大约97%的时间说:过早的优化是所有邪恶的根源.

这是Stack Overflow常常出现的问题,例如"哪个是最有效的循环机制","SQL优化技术?"等问题.(等等).这些优化提示问题的标准答案是分析您的代码并首先查看它是否是一个问题,如果不是,那么您的新技术就不再需要了.

我的问题是,如果某种技术不同但不是特别模糊或混淆,那真的可以被认为是过早的优化吗?

这是Randall Hyde的一篇名为"过早优化的谬误"的相关文章.

optimization premature-optimization

79
推荐指数
10
解决办法
1万
查看次数

优化C#/ .NET程序的技巧

如今优化似乎是一种迷失的艺术.所有程序员都没有从代码中挤出每一盎司的效率吗?经常在雪地里行走五英里的时候这样做?

本着回归丢失的艺术的精神,您知道的简单(或复杂)变化以优化C#/ .NET代码的一些提示是什么?因为它是如此广泛,取决于一个人想要完成什么,它有助于提供你的提示的背景.例如:

  • 当连接多个字符串时,请使用StringBuilder.请参阅底部的链接以了解相关信息.
  • 使用string.Compare两个字符串比较,而不是做这样的事情string1.ToLower() == string2.ToLower()

到目前为止,普遍的共识似乎是衡量关键.这种方式忽略了这一点:测量不会告诉你什么是错的,或者如果遇到瓶颈会怎么做.我遇到了字符串连接瓶颈一次,不知道该怎么办,所以这些提示很有用.

我甚至发布这个问题的意思是为了解决常见的瓶颈问题,以及在遇到这些问题之前如何避免它们.它甚至不一定是任何人应该盲目遵循的即插即用代码,而是更多关于获得对性能应该被考虑的理解,至少在某种程度上,并且需要注意一些常见的陷阱.

我可以看到,知道为什么提示有用以及应该应用的位置可能会有用.对于StringBuilder小费,我找到了很久以前在Jon Skeet网站上做过的帮助.

.net c# optimization

78
推荐指数
10
解决办法
4万
查看次数

性能问题:Java与C++

我一直听说C++比Java更有效(这就是大多数游戏都是用C++开发的原因).

我写了一个小算法来解决Java和C++中的"八皇后谜题",使用完全相同的算法,然后开始提高数字或方块.当到达20*20甚至22*22的检查板时,看起来Java更有效(3秒对C++的66秒).

我不知道为什么,但我从C++开始,所以我可能会犯一些巨大的性能错误,所以我很乐意接受任何可以帮助我理解正在发生的事情的信息.

下面是我在Java中使用的代码:

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

public class HuitDames {

    /**
     * La liste des coordnnées des dames.
     */
    private static List<Point> positions = new ArrayList<>();

    /**
     * Largeur de la grille.
     */
    private static final int LARGEUR_GRILLE = 22;


    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        int i = 1;
        placerDame(i);
        for (Point point : positions) {
            System.out.println("(" + point.x + "; " + point.y + ")"); …
Run Code Online (Sandbox Code Playgroud)

c++ java algorithm performance

68
推荐指数
4
解决办法
1万
查看次数

为什么递归优先于迭代?

迭代比递归更高效,对吧?那么为什么有些人认为递归比迭代更好(用他们的话来说更优雅)?我真的不明白为什么像Haskell这样的语言不允许迭代并鼓励递归?鼓励表现不佳的东西是不是很荒谬(当更高性能的选项即递归可用时也是如此)?请详细说明一下.谢谢.

language-agnostic iteration recursion performance

61
推荐指数
5
解决办法
5万
查看次数

效率:数组与指针

通过指针进行内存访问比通过数组进行内存访问更有效.我正在学习C,上面的内容在K&R中有说明.他们特别说

通过数组下标可以实现的任何操作也可以使用指针来完成.指针版本通常会更快

我使用visual C++解组了以下代码.(我是一个686处理器.我已禁用所有优化.)

int a[10], *p = a, temp;

void foo()
{
    temp = a[0];
    temp = *p;
}
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,我看到通过指针的内存访问需要通过数组对内存访问所采用的两条指令.以下是相应的代码.

; 5    : temp = a[0];

    mov eax, DWORD PTR _a
    mov DWORD PTR _temp, eax

; 6    : temp = *p;

    mov eax, DWORD PTR _p
    mov ecx, DWORD PTR [eax]
    mov DWORD PTR _temp, ecx
Run Code Online (Sandbox Code Playgroud)

请帮我理解.我在这里失踪了什么?


正如许多答案和评论所指出的那样,我使用了编译时常量作为数组索引,从而使得通过数组访问变得更容易.下面是汇编代码,其中变量作为索引.我现在有相同数量的指令通过指针和数组进行访问.我更广泛的问题仍然很好.通过指针进行内存访问并不会使其本身更有效.

; 7    :        temp = a[i];

    mov eax, DWORD PTR _i
    mov ecx, DWORD PTR _a[eax*4]
    mov DWORD PTR _temp, …
Run Code Online (Sandbox Code Playgroud)

c arrays performance pointers memory-access

57
推荐指数
6
解决办法
4万
查看次数

静态方法更有效吗?

在内存和时间方面,使方法静态更好吗?

c# performance static-methods

46
推荐指数
4
解决办法
1万
查看次数

使用大型库本身会使代码变慢吗?

我有一种心理tic,这让我不愿意在C和C++等低级语言中使用大型库(如GLibBoost).在我看来,我认为:

嗯,这个图书馆有数千个小时的时间,而且它是由那些比我更了解语言的人创造的.他们的作者和粉丝说这些库是快速可靠的,而且功能看起来非常有用,它肯定会阻止我(严重地)重新发明轮子.

该死的,我永远不会使用该库中的所有功能.它太大了,多年来可能会变得臃肿; 这是我的程序需要拖延的另一个球和链.

托沃兹咆哮(争议虽然它是)不完全把我的心脏放心无论是.

我的想法有什么依据,还是我只是不合理和/或无知?即使我只使用大型库的一个或两个功能,通过链接到该库我会产生运行时性能开销吗?

我确信它还取决于具体的库是什么,但我通常很想知道大型库是否会在技术层面上固有地引入低效率.

当我没有技术知识知道我是否正确的时候,我已经厌倦了对此的痴迷,嘀咕和担心.

请把我从痛苦中解救出来!

c c++ performance boost glib

46
推荐指数
5
解决办法
5316
查看次数

人们可以使用分析器,但为什么不停止程序呢?

如果某个东西正在使单线程程序占用,比如10倍,那么就可以在其上运行一个分析器.您也可以通过"暂停"按钮暂停它,您将看到它正在做什么.

即使它比它应该慢了10%,如果你停止它多次,不久你会看到它反复做不必要的事情.通常问题是在堆栈中间某处不是真正需要的函数调用.这不能衡量问题,但确实找到了.

编辑:反对意见主要假设您只采取1个样本.如果你是认真的,请采取10.任何一行代码,导致一定比例的浪费,如40%,将平均出现在该部分样本的堆栈上.瓶颈(单线程代码)无法隐藏它.

编辑:为了表明我的意思,许多反对意见的形式是"没有足够的样本,所以你看到的可能完全是虚假的" - 关于机会的模糊观点.但是,如果任何可识别的描述,不仅仅是在常规或常规活动中,在30%的时间内有效,那么在任何给定样本上看到它的概率是30%.

然后假设只采集了10个样本.在10个样本中看到问题的次数遵循二项分布,并且看到它0次的概率是.028.看到它1次的概率是.121.2次,概率为.233,而3次则为.267,之后下降.由于看到它少于两次的概率是.028 + .121 = .139,这意味着看到它两次或更多次的概率是1 - .139 = .861.一般规则是,如果您看到可以修复两个或更多样本的内容,则值得修复.

在这种情况下,在10个样本中看到它的机会是86%.如果你是14%没有看到它的人,那就去做更多的样品.(如果样本数量增加到20,那么两次或多次观察的几率会增加到99%以上.)所以它没有经过精确测量,但已经准确找到了,重要的是要了解它它可能很容易成为分析器无法实际找到的东西,例如涉及数据状态的东西,而不是程序计数器.

optimization performance profiling

45
推荐指数
12
解决办法
3万
查看次数

现代C++编译器的有效优化策略

我正在研究对性能至关重要的科学代码.该代码的初始版本已经编写和测试,现在,有了分析器,现在是时候从热点开始剃须周期了.

众所周知,编译器现在可以更有效地处理一些优化,例如循环展开,而不是手工编程的程序员.哪些技术还值得?显然,我会通过一个分析器来运行我尝试的所有内容,但是如果有传统的智慧关于什么往往有效,哪些无效,这将为我节省大量时间.

我知道优化非常依赖于编译器和体系结构.我正在使用针对Core 2 Duo的英特尔C++编译器,但我也对gcc或"任何现代编译器"的效果感兴趣.

以下是我正在考虑的一些具体想法:

  • 用手工卷取代STL容器/算法有什么好处?特别是,我的程序包括一个非常大的优先级队列(当前是a std::priority_queue),其操作占用了大量的总时间.这是值得研究的事情,还是STL实施可能是最快的?
  • 类似地,对于std::vector需要大小未知但上限相当小的s,用静态分配的数组替换它们是否有利可图?
  • 我发现动态内存分配通常是一个严重的瓶颈,消除它会导致显着的加速.因此,我很有兴趣通过值返回大型临时数据结构与通过指针返回相对于通过引用传递结果的性能权衡.有没有办法可靠地确定编译器是否会为给定方法使用RVO(假设调用者当然不需要修改结果)?
  • 编译器的缓存感知如何?例如,是否值得研究重新排序嵌套循环?
  • 鉴于该程序的科学性,浮点数被用于各处.我的代码中的一个重要瓶颈曾经是从浮点到整数的转换:编译器会发出代码来保存当前的舍入模式,更改它,执行转换,然后恢复旧的舍入模式---即使程序中没有任何内容永远改变了舍入模式!禁用此行为会大大加快我的代码速度.我应该注意哪些与浮点相关的类似问题?
  • C++被单独编译和链接的一个结果是编译器无法进行看起来非常简单的优化,例如在循环的终止条件下移动方法调用如strlen().有没有像我这样的优化,因为它们不能由编译器完成,必须手工完成?
  • 另一方面,我是否应该避免使用任何技术,因为它们可能会干扰编译器自动优化代码的能力?

最后,将某些类型的答案扼杀在萌芽状态:

  • 我知道优化在复杂性,可靠性和可维护性方面具有成本.对于此特定应用,提高性能值得这些成本.
  • 我知道最好的优化通常是改进高级算法,而且这已经完成了.

c++ optimization x86

45
推荐指数
6
解决办法
4233
查看次数

在C/C++中使用汇编语言

我记得在某处可以真正优化和加速代码的某些部分,程序员用汇编语言编写该部分.我的问题是 -

  1. 这种做法还在做吗?一个人怎么做?
  2. 不是用汇编语言编写有点过于繁琐和陈旧吗?
  3. 当我们编译C代码(带或不带-O3标志)时,编译器会进行一些代码优化并链接所有库并将代码转换为二进制对象文件.因此,当我们运行程序时,它已经处于最基本的形式,即二进制.那么如何诱导'汇编语言'有帮助?

我正在努力理解这个概念,非常感谢任何帮助或链接.

更新:根据dbemerlin的要求改写第3点 - 因为您可能能够编写比编译器生成的更有效的汇编代码,但除非您是汇编专家,否则您的代码运行速度会慢,因为编译器通常会比大多数人更好地优化代码.

c c++ optimization assembly compiler-optimization

43
推荐指数
4
解决办法
1万
查看次数