代码之家  ›  专栏  ›  技术社区  ›  rkellerm

用于明显操作的复杂代码

  •  1
  • rkellerm  · 技术社区  · 14 年前

    有时,主要为了优化目的,非常简单的操作被实现为复杂而笨拙的代码。

    一个例子是这个整数初始化函数:

    void assign( int* arg )
    {
        __asm__ __volatile__ ( "mov %%eax, %0" : "=m" (*arg));
    }
    

    然后:

    int a;
    assign ( &a );
    

    但实际上我不明白为什么是这样写的…

    你有没有看到过有真正原因的例子?

    5 回复  |  直到 14 年前
        1
  •  21
  •   JohnFx    14 年前

    在您的示例中,我认为这是错误假设的结果,即在程序集中编写代码自动更快。

    问题是编写这个的人不明白为什么程序集有时可以运行得更快。也就是说,您比编译器更了解您要做什么,有时可以使用这些知识在较低的级别上编写代码,这是基于不必假设编译器会这样做,从而提高性能的。

    在简单变量赋值的情况下,我严重怀疑这一点是否成立,并且代码的执行速度可能较慢,因为它具有管理堆栈上赋值函数的额外开销。请注意,它不会明显变慢,这里的主要成本是不可读和不可维护的代码。

    这是一个教科书中的例子,说明了为什么在不理解优化的原因的情况下不应该实现优化。

        2
  •  8
  •   Déjà vu    14 年前

    似乎汇编代码的目的是确保 *arg 每次都会执行int定位,以防止(故意)编译器在这方面进行任何优化。

    通常情况下 volatile 关键字在C++(和C)中使用,以告诉编译器该值不应保存在寄存器中(例如),并从该寄存器中重用(优化以更快地获得值),因为它可以被改变。 异步地 (通过外部模块、汇编程序、中断等)。

    例如,在函数中

      int a = 36;
      g(a);
      a = 21;
      f(a);
    

    在这种情况下,编译器 知道 变量 a 是函数的局部变量,不在函数外部进行修改(指针位于 例如,没有提供给任何调用)。它可以使用处理器寄存器来存储和使用 变量。

    总之,ASM指令似乎是按顺序注入到C++代码中的。 对该变量执行一些优化。

        3
  •  3
  •   wallyk    14 年前

    虽然有几个合理的理由可以在汇编中编写一些东西,但在我的经验中,这些都是不寻常的实际原因。在我能够研究基本原理的地方,它们归结为:

    年龄 :代码是很久以前编写的,所以对于处理那个时代的编译器来说,这是最合理的选择。一般来说,在大约1990年之前可以证明,imho。

    控制狂 :一些程序员 trust issues with the compiler 但不倾向于调查其实际行为。

    误解 :令人惊讶的是,使用汇编语言编写的任何代码都会比使用“笨拙的”编译器编写的代码效率更高,而使用其所有神秘的函数入口/出口代码等等。当然,一些编译器应该享有这种声誉。

    “酷” :当时间和金钱不是因素时,有什么更好的方法比一些阳刚之气(最好是难以理解的汇编语言)来支撑程序员显著升高的荷尔蒙水平呢?

        4
  •  1
  •   SmacL    14 年前

    您给出的示例似乎有缺陷,因为assign()函数比直接分配变量的速度慢,原因是调用带有参数的函数涉及堆栈使用,而只说int a=x易于编译到高效的代码而不需要堆栈。

    我唯一从使用汇编程序中受益的时候是通过手工优化编译器生成的汇编程序输出,那是在处理器速度通常在单兆赫范围内的时候。算法优化倾向于提供更好的投资回报,因为您可以获得数量级的改进而不是小倍数。正如其他人已经说过的,您进入汇编程序的唯一其他时间是编译器或语言是否不做您需要做的事情。有了C和C++,这是非常罕见的情况了。

    很可能是有人在炫耀他们知道如何编写一些琐碎的汇编程序代码,使下一个程序员的工作更加困难,而且可能是为了保护他们自己的工作而采取的一种半途而废的措施。对于给出的示例,代码比较混乱,可能比本机C慢,不太可移植,可能应该删除。当然,如果我在任何现代的C代码中看到任何内联assmebler,我希望有大量的注释来解释为什么它是绝对必要的。

        5
  •  0
  •   colithium    14 年前

    让编译器为您优化。这种“优化”不可能有任何帮助…永远!