Почему Math.DivRem неэффективен? - PullRequest
32 голосов
/ 15 января 2009

В моем компьютере этот код занимает 17 секунд (1000 миллионов раз):

static void Main(string[] args) {
   var sw = new Stopwatch(); sw.Start();
   int r;
   for (int i = 1; i <= 100000000; i++) {
      for (int j = 1; j <= 10; j++) {
         MyDivRem (i,j, out r);
      }
   }
   Console.WriteLine(sw.ElapsedMilliseconds);
}

static int MyDivRem(int dividend, int divisor, out int remainder) {
   int quotient = dividend / divisor;
   remainder = dividend - divisor * quotient;
   return quotient;
}

, в то время как Math.DivRem занимает 27 секунд.

.NET Reflector дает мне этот код для Math.DivRem:

public static int DivRem(int a, int b, out int result)
{
    result = a % b;
    return (a / b);
}

КСС

.method public hidebysig static int32 DivRem(int32 a, int32 b, [out] int32& result) cil managed
{
    .maxstack 8
    L_0000: ldarg.2
    L_0001: ldarg.0
    L_0002: ldarg.1
    L_0003: rem
    L_0004: stind.i4
    L_0005: ldarg.0
    L_0006: ldarg.1
    L_0007: div
    L_0008: ret
}

Теоретически это может быть быстрее для компьютеров с несколькими ядрами, но на самом деле не нужно выполнять две операции, во-первых, потому что процессоры x86 возвращают как частное, так и остаток , когда они целочисленное деление с использованием DIV или IDIV (http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-2.html#HEADING2-451)!

Ответы [ 11 ]

0 голосов
/ 15 января 2009

Вот мои номера:

15170 MyDivRem
29579 DivRem (same code as below)
29579 Math.DivRem
30031 inlined

Тест был немного изменен; Я добавил присваивание возвращаемому значению и выполнял сборку релиза.

Core 2 Duo 2.4

Мнение:

Вы, кажется, нашли хорошую оптимизацию;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...