这是我第一次尝试生成原生 C++ 代码, 然后从 c# 调用函数,以测试我在互操作/调用代码时听到的开销。 测试是简单的数学计算,首先是单次运行,然后是循环中的 10K 次迭代。
class Program
{
[DllImport("ExportTest.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void doWarmUp();
[DllImport("ExportTest.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int doOne();
[DllImport("ExportTest.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int doLongOne();
static void Main(string[] args)
{
doWarmUp();
Stopwatch sw = new Stopwatch();
int test;
sw.Reset();
sw.Start();
test = csdoOne();
sw.Stop();
Console.WriteLine("Res CsdoOne:{0} ", sw.ElapsedTicks);
sw.Reset();
sw.Start();
test = doOne();
sw.Stop();
Console.WriteLine("Res C++ doOne :{0} ", sw.ElapsedTicks);
sw.Reset();
sw.Start();
test = doLongOne();
sw.Stop();
Console.WriteLine("Res C++ doLongOne:{0}\tTics: {1} ", test, sw.ElapsedTicks);
sw.Reset();
sw.Start();
test = csdoLongOne();
sw.Stop();
Console.WriteLine("Res C# doLongOne:{0}\tTics: {1} ", test, sw.ElapsedTicks);
Console.Read();
}
static int csdoOne()
{
int res;
res = 5 * 4;
return res;
}
static int csdoLongOne()
{
int r1, r2;
r1 = 0; r2 = 0;
for (int i = 0; i < 10500; i++)
{
r1 = (5 * 4);
r2 = i * 2;
r1 += r2;
}
return r2;
}
}
如果看到 C++ 代码很有趣,我也会发布它,
我没有这样做,因为它实际上是两个函数中完全相同的代码
预热函数只是 void doWarmUp(){ return;}
,因为我注意到只有第一次调用有任何开销。
绘制的结果令人惊讶,因为我真的很喜欢 c#
Res Cs doOne: 4
Res C++ doOne: 17
Res c++ doLongOne: 21018 Tics: 30
Res C# doLongOne: 21018 Tics: 446
这只是简单的数学运算……我做错了什么吗?
最佳答案
您的测试存在缺陷。您只调用了一次非常的短方法,几乎没有什么可测量的。测量中的波动(可变性)将高于时间本身。这会使您的第一个方法计时无效。
您应该调用 doOne
十亿次并将结果除以十亿, float (而不是整数)。
不确定如何解释第二种方法的时间安排。您可能遇到过 .Net 在测试过程中进行垃圾收集的罕见时刻之一,从而增加了大量时间。这可以很容易地检查。多次运行测试。如果是这种情况,大多数时间将彼此接近,但有少数异常值。
此外,第二种方法也太短,无法在没有循环的情况下进行测量。在每秒运行数十亿条指令的处理器上很难测量 10K 次迭代。
关于c# - C++ 与 C# 相比,计算速度提高了 15 倍,这是合法的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33198136/