Paw*_*wel -1 c# intel raspberry-pi windows-10-iot-core raspberry-pi3
我做了一个简单的性能比较,侧重于使用C#的浮点运算,针对带有Windows 10 IoT的Raspberry Pi 3 Model 2,我将它与Intel Core i7-6500U CPU @ 2.50GHz进行了比较.
Raspberry Pi 3 Model B V1.2 - 测试结果 - 图表
英特尔酷睿i7-6500U CPU @ 2.50GHz - x64测试结果 - 图表
英特尔酷睿i7 仅比Raspberry Pi 3 快十二倍(x64)! - 根据那些测试.
准确度为11.67,并计算每个平台在这些测试中实现的最佳性能.两个平台在并行运行的四个线程中实现了最佳性能(非常简单,独立的计算).
问题:测量和比较这些平台的计算性能的正确方法是什么?目的是比较优化算法,机器学习算法,统计分析等领域的计算性能.因此,我的重点是浮点运算.
有一些基准测试(如MWIPS)和MIPS或FLOPS等测量.但我没有找到一种方法来比较不同的CPU平台的计算能力.
我找到了Roy Longbottom的一个比较(谷歌"Roy Longbottom的Raspberry Pi,Pi 2和Pi 3基准" - 我不能在这里发布更多链接)但根据他的基准测试,Raspberry Pi 3的速度只比英特尔酷睿i7快4倍(x64)建筑,MFLOPS比较).与我的结果非常不同.
以下是我执行的测试的详细信息:
测试是围绕应该迭代执行的简单操作构建的:
private static float SingleAverageCalc(float seed, long nTimes)
{
float x1 = seed, x2 = 0;
long n = 0;
for (; n < nTimes; ++n)
{
x2 = x2 + x1 * n;
}
return x2 / n;
}
Run Code Online (Sandbox Code Playgroud)
其中种子在调用函数随机生成的,N次是迭代的次数.意图是避免简单的编译时优化.
在单线程和多线程中,使用各种迭代次数(1M,10M,100M和1B)多次调用此测试函数.多线程测试如下:
private static async void RunTestMT(string name, long n, int tn, Func<float, long, float> f)
{
float seed = (float)new Random().NextDouble();
DateTime s1 = DateTime.Now;
List<IAsyncAction> threads = new List<IAsyncAction>();
for (int i = 0; i < tn; i++)
{
threads.Add( ThreadPool.RunAsync((operation) => { f(seed, n/tn); }, WorkItemPriority.High));
}
for (int i = 0; i < tn; i++)
{
threads[i].AsTask().Wait();
}
TimeSpan dt = DateTime.Now - s1;
Debug.WriteLine(String.Format("{0} ({1:N0}; {3}T): {2:mm\\:ss\\.fff}", name, n, dt, tn));
}
Run Code Online (Sandbox Code Playgroud)
测试已在调试模式下运行.应用程序构建为UWP(通用Windows平台).用于Raspberry Pi的ARM体系结构和用于Intel的x86.
测试已在调试模式下运行.
刚注意到最后一部分./捂脸.如果C#debug-mode与MSVC,gcc和clang等编译器中的调试模式类似,那就没用了,浪费了每个人的时间.
调试和优化代码之间的速度比在不同的微体系结构中不是恒定的.它因许多因素而异,包括正在测试的特定代码.如果有的话,额外的存储/重新加载将引入额外的延迟并且比ARM更多地惩罚Skylake,因为当像这样的延迟瓶颈并没有减慢速度时,Skylake能够实现更高的每时钟指令.
如果您没有使用任何类型的快速数学选项让C#重新排序FP操作,那么x2 = x2 + x1 * n;瓶颈主要是延迟(FP添加),而不是吞吐量.
FP数学不是关联的,因此重新排列它x2 += (x1 * n + x1 * (n+1)) + (x1 * (n+2) + x1 * (n+3))会改变结果.这种优化是关键,并且会使循环携带的依赖链(一个FP添加)短于独立依赖链的吞吐量.
如果C#有一个快速数学选项,允许编译器优化,就好像FP数学是关联的,智能编译器只会将整个循环转换为x2 = x1 * (nTimes * (nTimes+1) / 2).
一个不那么狡猾的编译器可能只是用一堆指令级并行来SIMD矢量化它,这将使Skylake能够实现每个时钟256b向量的两个FMA的峰值吞吐量.(每个向量是8个浮点数或4个双精度数,并且融合乘法数是a = a + b*c.)
在Skylake上,FMA的延迟为4个周期,因此您(或编译器)需要使用8 个累加器向量来使FMA执行单元饱和.(在Haswell和Broadwell,FMA延迟= 5个周期,因此您需要10个向量累加器来保持10*8单精度FMA在飞行中以最大化吞吐量.)
有关x86性能详细信息的更多信息,请参阅x86标记wiki.
当然,这也将有助于RPi中的ARM CPU,因为我认为它支持ARM的SIMD指令集.NEON具有128位向量.显然双精度矢量支持是AArch64中的新功能,但带NEON的32位ARM支持单精度矢量FP.
我不太了解ARM.
| 归档时间: |
|
| 查看次数: |
8841 次 |
| 最近记录: |