Net 4.6 RC x64 doppelt so langsam wie x86 ist (Release-Version):.NET 4.6 RC x64 ist doppelt so langsam wie x86 (Release-Version)
dieses Stück Code vor:
class SpectralNorm
{
public static void Main(String[] args)
{
int n = 5500;
if (args.Length > 0) n = Int32.Parse(args[0]);
var spec = new SpectralNorm();
var watch = Stopwatch.StartNew();
var res = spec.Approximate(n);
Console.WriteLine("{0:f9} -- {1}", res, watch.Elapsed.TotalMilliseconds);
}
double Approximate(int n)
{
// create unit vector
double[] u = new double[n];
for (int i = 0; i < n; i++) u[i] = 1;
// 20 steps of the power method
double[] v = new double[n];
for (int i = 0; i < n; i++) v[i] = 0;
for (int i = 0; i < 10; i++)
{
MultiplyAtAv(n, u, v);
MultiplyAtAv(n, v, u);
}
// B=AtA A multiplied by A transposed
// v.Bv /(v.v) eigenvalue of v
double vBv = 0, vv = 0;
for (int i = 0; i < n; i++)
{
vBv += u[i] * v[i];
vv += v[i] * v[i];
}
return Math.Sqrt(vBv/vv);
}
/* return element i,j of infinite matrix A */
double A(int i, int j)
{
return 1.0/((i + j) * (i + j + 1)/2 + i + 1);
}
/* multiply vector v by matrix A */
void MultiplyAv(int n, double[] v, double[] Av)
{
for (int i = 0; i < n; i++)
{
Av[i] = 0;
for (int j = 0; j < n; j++) Av[i] += A(i, j) * v[j];
}
}
/* multiply vector v by matrix A transposed */
void MultiplyAtv(int n, double[] v, double[] Atv)
{
for (int i = 0; i < n; i++)
{
Atv[i] = 0;
for (int j = 0; j < n; j++) Atv[i] += A(j, i) * v[j];
}
}
/* multiply vector v by matrix A and then by matrix A transposed */
void MultiplyAtAv(int n, double[] v, double[] AtAv)
{
double[] u = new double[n];
MultiplyAv(n, v, u);
MultiplyAtv(n, u, AtAv);
}
}
Auf meiner Maschine dauert x86 Release-Version 4,5 Sekunden, während die x64 9,5 Sekunden dauert. Gibt es ein bestimmtes Flag/eine bestimmte Einstellung für das x64?
UPDATE
Es stellt sich heraus, dass RyuJIT eine Rolle in dieser Frage hat. Wenn useLegacyJit
in app.config aktiviert ist, ist das Ergebnis anders und dieses Mal ist x64 schneller.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
<runtime>
<useLegacyJit enabled="1" />
</runtime>
</configuration>
UPDATE
Nun ist die Frage wurde auf die CLR-Team berichtet coreclr, issue 993
Ich bin nicht vertraut mit spektralen Normen umgekehrt, und das ist eine ganze Menge Code Erwägen. Könnten Sie uns eine Zusammenfassung dessen geben, was das tut - Hunderte oder Tausende von Matrixoperationen großer Gleitkomma-Doppelmatrizen mit Quadratwurzeln und Unterteilungen dort irgendwo? Kannst du das in beiden Profilen darstellen? Kannst du den generierten Assembler für irgendwelche offensichtlichen Pessimierungen betrachten? – Rup
Führen Sie einen Release-Build aus, und führen Sie ihn nicht in einem Debugger aus? –
Es lohnt sich, es ein paar Mal in einer 'for'-Schleife auszuführen und die ersten paar Iterationen zu ignorieren, da der JIT-Compiler beim ersten Mal seine Magie ausspielen muss. –