Ich überschreibe eine leistungsstarke C++ - Anwendung auf C#. Die C# -App ist merklich langsamer als das C++ - Original. Das Profiling sagt mir, dass die C# -App am meisten Zeit auf den Zugriff auf Array-Elemente verwendet. Daher erstelle ich einen einfachen Array-Access-Benchmark. Ich bekomme völlig andere Ergebnisse als others doing a similiar comparison.C++ - Array vs C# ptr Geschwindigkeit Verwirrung
Der C++ Code:
#include <limits>
#include <stdio.h>
#include <chrono>
#include <iostream>
using namespace std;
using namespace std::chrono;
int main(void)
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
int xRepLen = 100 * 1000;
int xRepCount = 1000;
unsigned short * xArray = new unsigned short[xRepLen];
for (int xIdx = 0; xIdx < xRepLen; xIdx++)
xArray[xIdx] = xIdx % USHRT_MAX;
int * xResults = new int[xRepLen];
for (int xRepIdx = 0; xRepIdx < xRepCount; xRepIdx++)
{
// in each repetition, find the first value, that surpasses xArray[xIdx] + 25 - i.e. we will perform 25 searches
for (int xIdx = 0; xIdx < xRepLen; xIdx++)
{
unsigned short xValToBreach = (xArray[xIdx] + 25) % USHRT_MAX;
xResults[xIdx] = 0;
for (int xIdx2 = xIdx + 1; xIdx2 < xRepLen; xIdx2++)
if (xArray[xIdx2] >= xValToBreach)
{
xResults[xIdx] = xIdx2; break;
}
if (xResults[xIdx] == 0)
xResults[xIdx] = INT_MAX;
}
}
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = duration_cast<milliseconds>(t2 - t1).count();
cout << "Elasped miliseconds " << duration;
getchar();
}
Der C# -Code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace arrayBenchmarkCs
{
class Program
{
public static void benchCs()
{
unsafe
{
int xRepLen = 100 * 1000;
int xRepCount = 1000;
ushort[] xArr = new ushort[xRepLen];
for (int xIdx = 0; xIdx < xRepLen; xIdx++)
xArr[xIdx] = (ushort)(xIdx % 0xffff);
int[] xResults = new int[xRepLen];
Stopwatch xSw = new Stopwatch(); xSw.Start();
fixed (ushort * xArrayStart = & xArr [0])
{
for (int xRepIdx = 0; xRepIdx < xRepCount; xRepIdx++)
{
// in each repetition, go find the first value, that surpasses xArray[xIdx] + 25 - i.e. we will perform 25 searches
ushort * xArrayEnd = xArrayStart + xRepLen;
for (ushort* xPtr = xArrayStart; xPtr != xArrayEnd; xPtr++)
{
ushort xValToBreach = (ushort)((*xPtr + 25) % 0xffff);
int xResult = -1;
for (ushort * xPtr2 = xPtr + 1; xPtr2 != xArrayEnd; xPtr2++)
if (*xPtr2 >= xValToBreach)
{
xResult = (int)(xPtr2 - xArrayStart);
break;
}
if (xResult == -1)
xResult = int.MaxValue;
// save result
xResults[xPtr - xArrayStart] = xResult;
}
}
} // fixed
xSw.Stop();
Console.WriteLine("Elapsed miliseconds: " + (xSw.ElapsedMilliseconds.ToString("0"));
}
}
static void Main(string[] args)
{
benchCs();
Console.ReadKey();
}
}
}
Auf meinem Computer (i7-3770), die C++ Version ist ca. 2x schneller als die C# -Version. Auf meinem Heimcomputer (i7-5820K) ist das C++ 1.5x schneller als die C# -Version. Beide werden in Release gemessen. Ich hoffte, dass ich durch die Verwendung von Zeigern in C# die Überprüfung der Array-Grenze vermeiden würde und die Leistung in beiden Sprachen gleich wäre.
So sind meine Fragen die folgenden:
- nach Hause kommen andere zu finden, C# der gleichen Geschwindigkeit wie C++ sein?
- Wie kann ich C# -Performance auf C++ - Ebene erhalten, wenn nicht über Zeiger?
- Was könnte der Treiber für verschiedene Beschleunigungen auf verschiedenen Computern sein?
Jeder Hinweis sehr geschätzt wird, Daniel
Ich hoffe, Sie führen den Benchmark ohne den Debugger (STRG + F5 statt F5 in Visual Studio) – xanatos
@xanatos: Ja. Danke für die Abkürzung. –
* ushort * xArrayEnd = xArrayStart + xRepLen; * Sie können dies außerhalb des 'for'-Zyklus verschieben – xanatos