38 Stimmen

Warum ist Math.DivRem so ineffizient?

In meinem Computer dauert dieser Code 17 Sekunden (1000 Millionen Mal):

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;
}

während Math.DivRem 27 Sekunden dauert.

.NET Reflector gibt mir diesen Code für Math.DivRem:

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

CIL

.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
}

Theoretisch könnte es für Computer mit mehreren Kernen schneller sein, aber eigentlich sollte es überhaupt nicht notwendig sein, zwei Operationen durchzuführen, weil x86 CPUs sowohl den Quotienten als auch den Rest zurückgeben, wenn sie eine Ganzzahldivision mit DIV oder IDIV durchführen (http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-2.html#HEADING2-451)!

0 Stimmen

Was passiert, wenn Sie .NET auf Nicht-x86 ausführen?

0 Stimmen

X64 ist eine Erweiterung von x86 und wenn die CPU nicht kompatibel mit x86 ist, handelt es sich lediglich um die Verwendung eines anderen Codes für das .net-Framework für diese CPU

0 Stimmen

Richtig, aber .NET ist auch als Mono implementiert und sollte daher auf anderen Architekturen wie ppc usw. laufen.

-3voto

howlingmadhowie Punkte 63

Es liegt zum Teil in der Natur des biests. Soweit ich weiß, gibt es keine allgemeine schnelle Möglichkeit, den Rest einer Division zu berechnen. Dies wird eine entsprechend große Anzahl von Taktzyklen benötigen, auch mit x hundert Millionen Transistoren.

0 Stimmen

Wenn Sie das Ergebnis haben, ist das Abrufen des Rests ein mul-sub, das schneller ist als ein anderer div.

0 Stimmen

Ja, aber du musst diesen Wert zuerst erhalten. Ich sehe keine Möglichkeit, dies in weniger als O(ln(n)) Zeit zu tun. Kannst du?

0 Stimmen

Das ist in der Tat wahr. Sie können den Rest nicht ohne eine Division bekommen, es sei denn, Sie möchten den Rest einer Potenz von zwei.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X