none
如何只进行一次除法运算同时得出商和余数? RRS feed

  • 问题

  • 我需要进行32位或64位的有符号或无符号的整数的除法运算,商和余数都要得到。本来这是个很简单的问题,但为了提高性能,我希望只进行一次除法运算就同时得到商和余数,而不是分别进行“/”和“%”运算(因为如果分别进行“/”和“%”的话,实际上是做了两次相同的除法,浪费性能)。

    在Math类中有一个方法(好像是DivRem吧)貌似能一次得出商和余数,但通过.Net Reflector反编译查看源码的话,就会发现它的内部还是分别进行了"/"和"%"运算,并不能提高性能。

    学过汇编的人都知道,实际上计算机在计算整数除法时是能够同时得出商和余数的,它们分别存放在不同的寄存器中。那么用C#能不能实现这样的功能呢?

    如果没有直接的方法的话,是否能够调用汇编实现?如果C#不能直接嵌入汇编的话,那么用C++嵌入汇编并编译为dll供C#调用是否可行?具体应该如何实现呢?(希望能够给出汇编代码和调用的方法,谢谢)

    2010年11月5日 2:59

答案

  • 你好 你可以尝试使用OpCodes 不过对你说的这种情况我没有运用过

    另外你说的用c++嵌入汇编然后提供dll给c#调用,在我看来这是不好的方法,因为我以前做过测试,同样的加减运算,用C/C++编译为dll供c#调用的效率比直接在c#中调用这些加减运算性能要差好多倍,差距特别大,预期你这样做不如直接调用C#的方法性能可能更好


    Raymond Tang (Microsoft C# MVP)
    Denn Ich Gehoer nur mir
    .NET交流群71840452
    微软中文论坛同城社区成都QQ群:74268428
    My Chinese Blog
    Chengdu,Sichuan Province,China
    能具体说说怎么使用OpCodes么?我也想让C#直接嵌入汇编呀,但实际上能办到么?要怎么做呢?

    Opcodes可以参考 http://msdn.microsoft.com/zh-cn/library/system.reflection.emit.opcodes_members%28v=VS.95%29.aspx

    不过我刚才大致查看了下好像并没有这样的指令
    其实这里的性能影响不大,建议不必要在这些地方花费时间


    Raymond Tang (Microsoft C# MVP)
    Denn Ich Gehoer nur mir
    .NET交流群71840452
    微软中文论坛同城社区成都QQ群:74268428
    My Chinese Blog
    Chengdu,Sichuan Province,China
    • 已标记为答案 062369 2010年11月5日 6:45
    2010年11月5日 4:51
    版主

全部回复

  • 你好 你可以尝试使用OpCodes 不过对你说的这种情况我没有运用过

    另外你说的用c++嵌入汇编然后提供dll给c#调用,在我看来这是不好的方法,因为我以前做过测试,同样的加减运算,用C/C++编译为dll供c#调用的效率比直接在c#中调用这些加减运算性能要差好多倍,差距特别大,预期你这样做不如直接调用C#的方法性能可能更好


    Raymond Tang (Microsoft C# MVP)
    Denn Ich Gehoer nur mir
    .NET交流群71840452
    微软中文论坛同城社区成都QQ群:74268428
    My Chinese Blog
    Chengdu,Sichuan Province,China
    2010年11月5日 3:39
    版主
  • 你好 你可以尝试使用OpCodes 不过对你说的这种情况我没有运用过

    另外你说的用c++嵌入汇编然后提供dll给c#调用,在我看来这是不好的方法,因为我以前做过测试,同样的加减运算,用C/C++编译为dll供c#调用的效率比直接在c#中调用这些加减运算性能要差好多倍,差距特别大,预期你这样做不如直接调用C#的方法性能可能更好


    Raymond Tang (Microsoft C# MVP)
    Denn Ich Gehoer nur mir
    .NET交流群71840452
    微软中文论坛同城社区成都QQ群:74268428
    My Chinese Blog
    Chengdu,Sichuan Province,China
    能具体说说怎么使用OpCodes么?我也想让C#直接嵌入汇编呀,但实际上能办到么?要怎么做呢?
    2010年11月5日 3:45
  • dear
    数学运算对于计算机来讲,本来就是一个很不简单的演算法

    計算機在計算整數除法時是能夠同時得出商和餘數的

    你确保它一定是能同时得到??这取决于底层演算运算,除非你自己改写底层

    个人觉得不需要浪费時間优化这样的代码

    秘訣無它,唯勤而已
    2010年11月5日 4:26
  • 你好 你可以尝试使用OpCodes 不过对你说的这种情况我没有运用过

    另外你说的用c++嵌入汇编然后提供dll给c#调用,在我看来这是不好的方法,因为我以前做过测试,同样的加减运算,用C/C++编译为dll供c#调用的效率比直接在c#中调用这些加减运算性能要差好多倍,差距特别大,预期你这样做不如直接调用C#的方法性能可能更好


    Raymond Tang (Microsoft C# MVP)
    Denn Ich Gehoer nur mir
    .NET交流群71840452
    微软中文论坛同城社区成都QQ群:74268428
    My Chinese Blog
    Chengdu,Sichuan Province,China
    能具体说说怎么使用OpCodes么?我也想让C#直接嵌入汇编呀,但实际上能办到么?要怎么做呢?

    Opcodes可以参考 http://msdn.microsoft.com/zh-cn/library/system.reflection.emit.opcodes_members%28v=VS.95%29.aspx

    不过我刚才大致查看了下好像并没有这样的指令
    其实这里的性能影响不大,建议不必要在这些地方花费时间


    Raymond Tang (Microsoft C# MVP)
    Denn Ich Gehoer nur mir
    .NET交流群71840452
    微软中文论坛同城社区成都QQ群:74268428
    My Chinese Blog
    Chengdu,Sichuan Province,China
    • 已标记为答案 062369 2010年11月5日 6:45
    2010年11月5日 4:51
    版主
  • dear
    数学运算对于计算机来讲,本来就是一个很不简单的演算法

    計算機在計算整數除法時是能夠同時得出商和餘數的

    你确保它一定是能同时得到??这取决于底层演算运算,除非你自己改写底层

    个人觉得不需要浪费优化这样的代码

    秘訣無它,唯勤而已

    起码对于主流平台而言,底层实现都应该是差不多的。从除法原理来讲,做整数除法是能够同时得到商和余数的;从计算机实现来讲,汇编的DIV指令也确实做到了这一点,并且把商和余数分别存放在不同的寄存器中。求商和求余其实是一个不可分割的整体,反而没有单独求其中一个的指令。

    我提出这个问题,旨在最大限度地挖掘计算机的潜能,我不认为这是什么“浪费”,就当成是学术研究还不行么?

    2010年11月5日 4:58
  • dear
    小弟并非不认同你的想法,只是认为你的探讨方向并非适用C#,
    并进高阶语言本旨是为了开发上的快速,以及物件上的重用,
    你所探讨的方向应该是往低阶语言着手进行。

    虽然是除法原理,但是对于计算机而言,它本来就不懂除法的,是人写出演算逻辑,并放在电脑上执行的,
    这也就是为何每一种语言对演算法执行的效能都会不太一漾,因为底层的原件都不一样。

    您谈到彙編的DIV指令能一次算出馀跟商,那就是写DVI指令底层的人写的演算法,他把演算节果放到两个记忆体里,
    至于他是如何得到这两个结果?也只有他知道了。
    秘訣無它,唯勤而已
    2010年11月5日 6:39
  • 目前,对于 x86 架构的主流 PC 机来讲,除法运算所花费的时间 (32 位),一般都在 Exp(-6) 数量级,即使重复两次 DIV 指令,这个性能损耗仅仅只是百万分之一秒而已。楼主也不必要太看中这种界别的性能问题。

    现在几乎所有 CPU,都支持浮点数运算扩展指令集,对于整数/浮点数除法的计算速度可能会远低于 Exp(-6),举个例子,玩游戏的时候,所有屏幕上的图像,都是通过点画出来的;每个点的运动呈现,都需要无数的除法运算,但您丝毫不觉得图像停顿和滞后,除法属于一种硬件级别的实现,它不应该被看作为性能损耗。

    不错,研究性能问题是很好的,但是,对于 .NET Framework,其性能问题的关键是如何写代码以及如何设计您的架构。比如,直接用 goto 远远比用 for, while 的性能好,但为什么大多数高级语言不推荐用它呢?各种不同的语言有不同的应用范围。C# 是一种托管的高级语言,它不直接提供硬件抽象层的访问,也不可能直接嵌入汇编 (C# 的本机代码是 JIT 出来的,根本无法把本机汇编直接嵌入到编译好的 EXE/DLL 中),它是面向应用的,而不是给大家做硬件实现级别的研究的。说白了,通过 C# 根本上看不到硬件实现。

    楼主要学术研究,可以去搞 C/C++,或者直接搞 Win32 汇编。这样可能会更加适合一些。


    Mark Zhou
    2010年11月5日 8:44