FLOP/s是什么?它是否是衡量性能的好指标?

52
我被要求测量Fortran程序在多CPU系统上解决微分方程的性能。我的雇主坚持要我测量FLOP/s(每秒浮点运算次数)并将结果与基准(LINPACK)进行比较,但我不确定这是正确的方法,因为没有人能向我解释什么是FLOP。
我对FLOP的定义进行了一些研究,并得到了一些相互矛盾的答案。其中最流行的答案之一是“1 FLOP = 一次加法和一次乘法运算”。这是真的吗?如果是这样,从物理上讲,这到底意味着什么?
无论我最终使用哪种方法,它都必须是可扩展的。代码的某些版本解决具有数百万未知数的系统,并需要几天才能执行。
在我的情况下(即“Fortran代码在数百个CPU上反复进行大量算术计算”的摘要),还有哪些其他有效的性能测量方法?
9个回答

57

这是一种相当不错的性能度量,只要你确切地了解它所测量的内容。

FLOPS表示每秒浮点运算次数,正如名称所示。但实际上构成一个FLOP的内容可能因CPU而异(例如,有些CPU可以将加法和乘法视为一种操作,而其他CPU则不能)。这意味着作为一种性能度量,它与硬件非常接近,这意味着1)您必须知道您的硬件来计算给定架构上理想的FLOPS,并且必须知道您的算法和实现来确定它实际包含多少浮点操作。

无论如何,它是检查您如何利用CPU的有用工具。如果您知道CPU的理论峰值FLOPS性能,那么您可以计算出您使用CPU的浮点单位的效率,这通常是难以高效利用的单位之一。在CPU能力的30%运行的程序具有优化的余地。在70%运行的程序可能不会再变得更有效,除非您改变基本算法。对于像您的数学密集型算法,这几乎是衡量性能的标准方式。您可以简单地测量程序运行的时间,但这会因CPU而异。但是,如果您的程序的CPU利用率为50%(相对于峰值FLOPS计数),则这是一个更加恒定的值(它仍然会在不同的CPU架构之间有所变化,但比执行时间更为一致)。

但是,了解“我的CPU能够达到X GFLOPS,而我实际上只实现了其吞吐量的20%”是高性能软件中非常有价值的信息。这意味着除浮点运算以外的某些内容阻碍了您的效率,并且防止了FP单位有效地工作。由于FP单位占据大部分工作量,这意味着您的软件存在问题。

测量"My program runs in X minutes"很容易,如果你觉得不可接受,那么当然可以尝试减少30%,但是除非你准确地计算出有多少工作正在进行,以及CPU在峰值时的确切性能,否则你就不知道是否可能。如果你甚至不知道CPU基本上是否能每秒运行更多指令,你要花费多少时间来优化呢?

通过在FP操作之间具有太多依赖关系或具有太多分支或类似物以防止有效调度,很容易防止CPU的FP单元被有效利用。如果这正是阻碍你实现的原因,你需要知道 "我没有获得应该可能的FP吞吐量,因此显然我的代码中的其他部分正在阻止FP指令在CPU准备发出时可用。"

为什么需要其他方式来衡量性能? 按照老板的要求计算FLOPS是否有错呢?;)


他们确实没有。他们所拥有的是每种类型指令需要花费多长时间以及每个指令能发出的频率(以及可以并行运行多少个指令)的明确限制。通过这些限制,您可以推导出理论峰值FLOPS。 - jalf
1
@caglarozdag:正如@tgamblin所说,你通常可以忘记在任何CPU上达到峰值FLOPS。这是不可能的。在我看来,大多数应用程序中,如果你达到了CPU理论峰值FLOPS的50%,你应该为自己鼓掌。也许你能够达到70%,但那时你真的应该觉得自己很幸运。但是,如果你只有10%的运行效率(这种情况出现得惊人地频繁),那么可能还有改进的空间。 - jalf
旁枝末节的问题:为什么性能以每秒浮点运算次数(FLOPS)来衡量,而不考虑每秒整数运算次数? - Shailen
@shailenTJ 因为 FLOPS 起源于科学计算社区,而那些人对整数性能真的不太关心。他们想要的是浮点数运算,而这个数字实际上就是最重要的。历史上,整数指令比浮点操作便宜得多,因此与浮点操作相关的效率几乎总是占据着整体性能的主导地位。 - jalf
还有其他的衡量性能的方式。MIPS(每秒百万条指令)是另一种更侧重整数的方式。基本上,人们以对他们重要的方式衡量性能。而FLOPS则对那些运行大量浮点代码的人很有吸引力。 :) - jalf
显示剩余6条评论

30

我想补充几个细节:

  • 除法是特殊的。由于大多数处理器可以在单个周期内执行加、比较或乘法,因此它们都被视为一个flop。但是除法总是需要更长的时间。具体需要多长时间取决于处理器,但在HPC社区中有一种约定俗成的标准,即将一个除法计为4个flop。

  • 如果处理器有一个融合乘加指令,可以在单个指令中执行乘法和加法——通常是A += B * C——那么计为2个操作。

  • 始终要小心区分单精度flop双精度flop之间的差别。一个能够执行许多单精度gigaflops的处理器可能只能执行其中的一小部分双精度gigaflops。AMD Athlon和Phenom处理器通常可以执行一半的双精度flop与单精度flop相比。ATI Firestream处理器通常只能执行1/5的双精度flop与单精度flop相比。如果有人试图向您销售处理器或软件包,并且只引用了flop而没有说明是哪种精度的flop,您应该提醒他们。

  • 诸如megaflop、gigaflop、teraflop等术语在常用中。这些术语指的是1000的倍数,而非1024。例如,1兆flop = 1,000,000 flop/sec而不是1,048,576。就像磁盘驱动器大小一样,这可能会引起一些混淆。


2
你有除法被视为特殊/计算为4个FLOPS的引用吗?很想详细阅读更多相关内容。 - mprat
2
@mprat:除法和乘法之间的成本比取决于如何使用它。对于现代CPU(自2015年以来),“4 flops”听起来相当虚假。偶尔的x86-64 AVX vdivps不在关键路径上,其执行吞吐资源的成本与vmulps相同。OoO exec可以隐藏延迟,并且对于前端而言只有1个uop(在某些CPU上),因此只要您不需要比非完全流水线化的除法器更频繁地进行除法运算即可处理。浮点除法与浮点乘法 - Peter Cordes

13

这是一个老问题,有一些流行的答案,但在我看来并不完美。

“FLOP”是浮点数运算。 “FLOPS”可以指以下两种情况之一:

  • “FLOP”的复数形式(即“操作X需要50个FLOPs”)
  • 第一种意义上的FLOPs速率(即每秒浮点数运算次数)

如果从上下文中无法明确是哪一种意思,通常通过将前者写为“FLOPs”而将后者写为“FLOP/s”来消除歧义。

所谓的FLOPs是为了区别于其他类型的CPU操作,例如整数运算、逻辑运算、位运算、内存操作和分支操作,它们具有不同的成本(即“需要不同的时间长度”)。

"FLOP计数"的实践可以追溯到科学计算的早期,相对而言,FLOP非常昂贵,每个FLOP需要很多CPU周期。例如,80387数学协处理器单次乘法需要大约300个周期。这是在流水线技术和CPU时钟速度与内存速度差距真正拉开之前:内存操作只需一两个周期,分支(“决策制定”)也同样便宜。在那个时候,如果你能够用十几个内存访问或分支来替代一个FLOP,你就会获得收益。因此,在过去,计算FLOP数量并不过多关注内存引用和分支是有意义的,因为FLOP在执行时间中占主导地位,因为它们相对于其他类型的操作来说非常昂贵。

最近情况已经反转。FLOPs变得非常便宜 - 任何现代的英特尔核心每个周期可以执行大约两个FLOP(尽管除法仍然相对昂贵) - 而内存访问和分支相对更加昂贵:L1缓存命中可能需要3或4个周期,从主存储器获取则需要150-200个周期。考虑到这种反转,不再是以前通过消除FLOP来换取内存访问会产生收益;事实上,这是不太可能的。同样,即使FLOP是多余的,通常也更便宜“只是做”FLOP,而不是决定是否要执行它。这与25年前的情况完全相反。

很不幸,将盲目计算FLOP作为算法优劣的绝对度量已经过时。现代科学计算更多地涉及内存带宽管理——试图让执行FLOP的执行单元不断地获取数据——而不是减少FLOP数量。提到LINPACK(20年前基本上被LAPACK淘汰了)让我怀疑你的雇主可能是一个非常老派的学校,还没有内化建立性能期望不仅仅是FLOP计数的事实。如果具有更有利的内存访问模式和数据布局,则执行两倍FLOP的求解器仍然可能比另一个快20倍。
总之,计算密集型软件的性能评估变得比以前复杂得多。FLOP变得便宜的事实,与内存操作和分支成本的巨大可变性相结合,使情况变得极其复杂。当涉及评估算法时,简单的FLOP计数不再提供整体性能期望。
也许更好的思考性能预期和评估的方式是采用所谓的屋顶线模型,它远非完美,但具有同时考虑浮点和内存带宽问题的权衡的优势,提供了更丰富和深入的“二维图像”,使性能测量和性能预期可以进行比较。值得一看。

1
总体来说是个不错的答案;有一个小问题:L1缓存命中的成本可能是3或4个时钟周期 - 这是大约的延迟(在Haswell/Skylake上进行SIMD FP加载更像是5或6个时钟周期),但它以每个时钟节拍2次负载的吞吐量进行流水线处理。在大多数代码中,乱序执行可以轻松隐藏L1d命中延迟(其中数组索引不依赖于先前的FP计算),这就是为什么我们有OoO exec的原因。 - Peter Cordes

4
"将结果与基准进行比较",然后做什么?
FLOPS意味着您需要:
1)每个工作单位的FLOPs。
2)该工作单位的时间。
假设您有一些输入文件,它通过某些循环执行1,000次迭代。循环是一个方便的工作单位。它被执行了1,000次。用时1小时。
循环中有一些加法、乘法和除法以及平方根。您可以计算加法、乘法和除法。您可以在源代码中计算这些,查找+、*和/。您还可以找到编译器的汇编语言输出,并在那里计算它们。您可能会得到不同的数字。哪个是正确的?问问您的老板。
您可以计算平方根,但您不知道它实际上在乘法和加法方面做了什么。因此,您需要像基准测试乘法与平方根一样来了解平方根需要多长时间。
现在您知道了循环中的FLOPS。您知道运行它1,000次的时间。您知道每秒的FLOPS。
然后您查看LINPACK并发现您更慢了。现在怎么办?您的程序不是LINPACK,并且比LINPACK慢。你的代码会慢得多。除非您的代码与LINPACK的优化时间相同,否则您将会更慢。
这是另一部分。您的处理器针对各种基准测试有一些定义的FLOPS评级。您的算法不是这些基准测试之一,因此您低于基准测试。这是坏事吗?还是这是不成为基准测试的明显结果?
可行的结果是什么?
针对某些基准测试代码库的测量只会告诉您,您的算法不是基准测试算法。您将会不同;通常更慢。
显然,针对LINPACK的测量结果将是(a)您不同,因此(b)您需要进行优化。
只有在与自己进行比较时,测量才真正有价值。而不是一些假定的指令集,而是您自己的指令集。测量自己的性能。进行更改。查看您的性能-与自己相比-是否变得更好或更差。
FLOPS并不重要。重要的是每个工作单位的时间。您永远无法匹配硬件的设计参数,因为您没有运行硬件设计师预期的基准测试。
LINPACK并不重要。重要的是您的代码库以及您正在进行的更改来改善性能。

我相信LINPACK解决了一个矩阵系统(当时LINPACK的开发人员选择的一个相对随意的问题),而我们的算法恰好具有相同的目的。我认为我的老板意识到它会比LINPACK慢,只是想看看慢多少。 - caglarozdag
FLOPS 在计算机编程中非常有用,它可以衡量 CPU 浮点运算单元的利用率。由于这通常是相当难以高效利用的,因此 FLOPS 对高性能计算等方面来说是有用的信息。它告诉您程序结构阻止了最重要的 CPU 资源的高效利用。 - jalf

1

FLOPS即浮点运算每秒。例如,如果您需要一秒钟完成一个操作(如将两个值相加、相减、相乘或相除,并返回结果),则您的性能就是1 FLOPS。最近的CPU可以轻松实现数十亿次浮点运算,即数十亿次浮点运算每秒。


1

我会尽可能地让它运行得更快,这需要找出它花费时间的地方,特别是如果有可以避免的函数调用。

我通过简单的方法来实现,就是在它运行时中断几次,看看它在做什么。以下是我发现的一些事情:

  • 大部分时间都花在计算导数和/或雅可比矩阵上。其中很多时间都用于数学函数调用,例如exp()log()sqrt()。通常这些函数会重复使用相同的参数,可以进行记忆化处理。(大幅加速)

  • 由于积分容限比必要的更紧,因此很多时间都花在了计算过多次的导数上。(更快)

  • 如果使用隐式积分算法(如DLSODE Gear),因为方程被认为是僵硬的,那么它们可能并不是僵硬的,可以使用类似龙格-库塔的算法(DVERK)。 (更快)

  • 如果模型是线性的(DGPADM),则可能可以使用矩阵指数算法。这对性能和精度都有很大提升,并且不受僵硬性的影响。(更快)

  • 在调用堆栈中更高层次上,可能会反复执行相同的积分,但参数略有不同,以确定解相对于这些参数的前向或中心差分梯度。如果微分方程本身是可微的,则可能通过解析地或通过增加灵敏度方程来获得这些梯度。这不仅更快,而且更精确,可以进一步提高堆栈上层的速度。

你可以将每一层堆栈视为寻找优化事项的机会,并且速度提升将不断累积。当您转向多CPU时,假设它是可并行的,那么它应该提供自己的乘法因子。

回到FLOPs。您可以尝试最大化每秒钟的FLOPs,但通过在堆栈的所有级别上进行优化,最小化每次运行的FLOPs也可以更有用。无论如何,只是测量它们几乎什么都告诉不了您。


0

你的雇主是对的。
衡量你的Fortran程序(或任何其他程序)有效性的唯一方法是测试它是否符合标准基准,如果有的话。

至于FLOPs,它代表“每秒浮点运算次数” - 可以在维基百科上看到定义


0

我认为测量FLOPS并不是非常有用。

FLOPS的数量只能告诉您算法正在使CPU保持多忙,但不能告诉您算法本身表现如何。

您可能会发现两个不同的算法会导致处理器执行相同数量的FLOPS,但其中一个可以在一半的时间内提供您所需的结果。

我认为您最好关注更高级的统计数据,例如每单位时间解决的微分方程的数量(毕竟这是您的算法的目的)。

另一方面,测量实现的FLOPS数量可能有助于改善您的算法,因为它将告诉您CPU的繁忙程度。


FLOPS显示您当前的实现与同一算法的最优实现相差多少。是的,如果您知道更有效的算法,应该使用它,但希望您已经在使用已知的最佳算法,然后FLOPS在优化中很重要。是的,这很有用。 - jalf

0

如何测量T-FLOPS

"(# of parallel GPU processing cores multiplied by peak clock speed in MHz multiplied by two) divided by 1,000,000

公式中的数字2源于某些GPU指令可以在一个周期内执行两个操作,而且由于teraFLOP是衡量GPU最大图形潜力的度量标准,因此我们使用该度量标准。

让我们看看如何使用该公式来计算Xbox One的teraFLOPS。该系统的集成图形具有768个并行处理核心。 GPU的峰值时钟速度为853MHz。当我们将768乘以853,然后再乘以2,然后将该数字除以1,000,000,我们得到1.31 teraFLOPS。

https://www.gamespot.com/gallery/console-gpu-power-compared-ranking-systems-by-flop/2900-1334/


2016年显卡价格比较: "这些是理论性能数据,我们了解到这些数据通常会过于乐观,高出实际数值的十倍。因此,根据这些数据,实际价格大约在每GFLOPS 0.03美元至0.3美元之间。我们收集了单精度和双精度的数据,但最便宜的价格相似。"

https://aiimpacts.org/current-flops-prices/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接