我使用C#进行了一次简单的性能比较,主要针对浮点运算,针对 Raspberry Pi 3 Model 2 进行了 Windows 10 IoT 我将它与 Intel Core i7-6500U CPU @ 2.50GHz 进行了比较。
Raspberry Pi 3 Model B V1.2 - Test Results - Chart
Intel Core i7-6500U CPU @ 2.50GHz - x64 Test Results - Chart
英特尔酷睿i7 仅比Raspberry Pi 3快12倍(x64)! - 根据那些测试。
确切地说,因子 11.67 ,并计算出在每个平台上的这些测试中实现的最佳性能。两个平台在并行运行的四个线程中实现了最佳性能(非常简单,独立的计算)。
问题:测量和比较这些平台的计算性能的正确方法是什么?目的是比较优化算法,机器学习算法,统计分析等领域的计算性能。因此,我的重点是浮点运算。
有一些基准测试(如MWIPS)和MIPS或FLOPS等测量。但我没有找到一种方法来比较不同的CPU平台的计算能力。
我找到了Roy Longbottom的一个比较(谷歌和#34; Roy Longbottom&#Raspberry Pi,Pi 2和Pi 3基准测试" - 我不能在这里发布更多链接)但是根据他的基准测试Raspberry Pi 3仅比英特尔酷睿i7(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;
}
其中种子在调用函数中随机生成, nTimes 是迭代次数。意图是避免简单的编译时优化。
在单线程和多线程中,使用各种迭代次数(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));
}
测试已在调试模式下运行。应用程序构建为UWP(通用Windows平台)。用于Raspberry Pi的ARM体系结构和用于Intel的x86。
答案 0 :(得分:6)
测试已在调试模式下运行。
刚刚注意到这最后一部分。 /捂脸。如果C#debug-mode与MSVC,gcc和clang等编译器中的调试模式类似,那么that's useless就浪费了每个人的时间。
调试和优化代码之间的速度比在不同的微体系结构中不是一成不变的。它因许多因素而异,包括正在测试的特定代码。如果有的话,额外的存储/重新加载将引入额外的延迟并且比ARM更多地惩罚Skylake,因为当像这样的延迟瓶颈不会减慢时,Skylake能够实现更高的每时钟指令。
如果您没有使用任何类型的快速数学选项让C#重新排序FP操作,x2 = x2 + x1 * n;
主要是延迟(FP添加)的瓶颈,而不是吞吐量。
FP math is not associative,因此将其重新排列为x2 += (x1 * n + x1 * (n+1)) + (x1 * (n+2) + x1 * (n+3))
会改变结果。这种优化是关键,并且会使循环携带的依赖链(一个FP add)比独立依赖链的吞吐量更短。
如果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位向量。显然,双精度矢量支持is new in AArch64,但带NEON的32位ARM支持单精度矢量FP。
我对ARM不太了解。
答案 1 :(得分:1)
问题:测量和比较这些平台的计算性能的正确方法是什么? &LT;
我的策略是基于没有一个单一的衡量指标可以代表。因此,我有许多衡量不同性能特征的基准。
在我引用的主要RPi文档中,与Core i7的比较显示了古老的标准基准,Whetstone,Dhrystone,Linpack和Livermore Loops。这些提供了15种不同的测量,其中i7的速度提高了4到14倍,而CPU MHz为3.25。然后还有许多其他基准测试,未进行比较,通常使用来自高速缓存或RAM的数据进行60次不同功能的测量。
你引用的数字(错误的方式说RPi 3快了4倍)来自使用四个内核的多线程报告,你似乎正在比较RPi 3的MFLOPS / MHz比率为5.025和Core i7的23比率,对于RPi测量的MFLOPS为6030,对于I7测量为89700,快14.9倍。这些用于使用NEON用于RPi和SSE用于Intel的单精度计算。还引用了使用AVX 1指令的Intel的MFLOPS / MHz比率,表示177840的i7 MFLOPS。此MP-MFLOPS测试还包括使用更少计算和基于缓存或RAM的数据的进一步测量。引用的最大速度基于for循环中每个数据字的32个运算:
x[i] = (x[i]+a)*b-(x[i]+c)*d+(x[i]+e)*f-(x[i]+g)*h+(x[i]+j)*k-(x[i]+l)*m+(x[i]+o)*p-(x[i]+q)*r+(x[i]+s)*t-(x[i]+u)*v+(x[i]+w)*y;
为获得最佳RPi MP MFLOPS性能,您应该看到高性能Linpack Benchmark结果: