什么是FLOP / s,这是一个很好的衡量performance?
我被要求测量一个fortran程序的性能,这个程序可以在多CPU系统上求解微分方程。 我的雇主坚持我测量FLOP / s(浮动操作每秒),并将结果与基准( LINPACK )进行比较,但我不相信这是一条路,因为没有人能向我解释FLOP是什么。
我做了一些关于FLOP的研究,得到了一些相当矛盾的答案。 我得到的最受欢迎的答案之一是“1 FLOP =加法和乘法运算”。 真的吗? 如果是这样,身体上又是什么意思呢?
无论我最终使用什么方法,它必须是可扩展的。 一些版本的代码解决了数百万未知数的系统,需要数天的时间来执行。
在我的情况下,还有哪些其他有效的衡量性能的方法(我的情况摘要是fortran代码,在几百个CPU上一遍又一遍地进行大量的算术运算)?
只要你确切地理解它的措施,这是一个非常体面的衡量标准。
FLOPS正如其名字所暗示的每秒浮点运算次数,FLOP的构成因CPU而异。 (一些CPU可以执行加法和乘法作为一个操作,而另一些则不能)。 这意味着作为一个性能指标,它与硬件非常接近,这意味着1)您必须了解您的硬件,才能在给定的架构上计算出理想的FLOPS,并且您必须知道您的algorithm和实现,才能弄清楚它实际上包含许多浮点操作。
无论如何,这是检查CPU利用率的有用工具。 如果您知道CPU在FLOPS中的理论峰值性能,可以计算出您使用CPU的浮点单元的效率,这往往是难以有效利用的。 一个程序运行CPU的30%的FLOPS能力,有优化的空间。 除非你改变基本algorithm,否则运行在70%的效率可能不会更高效。 对于像你这样的math重algorithm,这几乎是测量性能的标准方法。 您可以简单地衡量一个程序运行多长时间,但是这取决于CPU的变化。 但是如果你的程序有50%的CPU利用率(相对于峰值FLOPS计数),这是一个比较恒定的值(它在不同的CPU体系结构之间依然会有所不同,但是它比执行时间更加一致)。
但是知道“我的CPU能支持X GFLOPS,而且实际上只能达到20%的吞吐量”是高性能软件中非常有价值的信息。 这意味着浮点运算以外的东西会阻止您,并阻止FP单元高效工作。 而且由于FP单元构成了大部分工作,这意味着你的软件有问题。
测量“我的程序在X分钟内运行”很容易,如果您觉得这是不可接受的,那么当然可以去“我不知道能否砍掉30%”,但是您不知道这是否可能您可以确切了解正在进行的工作量,以及CPU能够达到的峰值功率。 如果您甚至不知道CPU是否能够每秒钟运行更多指令,那么您需要花多less时间来优化这个指令?
由于FP操作之间的依赖太多,或者分支太多或者类似的操作妨碍了高效的调度,因此很难防止CPU的FP单元被有效利用。 如果这是你的执行回来,你需要知道这一点。 你需要知道“我没有获得应该可以实现的FP吞吐量,所以当我的代码的其他部分阻止FP指令在CPU准备好发出时可用”。
为什么你需要其他方法来衡量performance? 刚才老板问你要做FLOPS计数有什么不对? ;)
我只想添加一些更好的观点:
-
师是特别的。 由于大多数处理器可以在一个周期内进行加法,比较或乘法运算,所有这些都被视为一个触发器。 但分工总是需要更长时间。 多长时间取决于处理器,但在HPC社区有一种事实上的标准,将一个部门计为4个触发器。
-
如果一个处理器有一个融合的乘 – 加指令,在一条指令中进行乘法和加法运算,通常为A + = B * C – 算作2次运算。
-
在区分单精度触发器和双精度触发器时要小心。 能够有如此多的单精度千兆位处理器的处理器可能只能是许多双精度千兆位的一小部分。 AMD Athlon和Phenom处理器通常可以做单精度的双精度触发器的一半。 ATI Firestream处理器通常可以做到单精度的双精度触发器的1/5。 如果有人试图向你推销一个处理器或一个软件包,他们只是不加说明地引用翻牌,你应该打电话给他。
-
megaflop,gigaflop,teraflop等术语是常用的。 这些是指1000的因子, 而不是1024 。 例如,1百万次翻转= 1,000,000次翻转/秒不是1,048,576次。 就像磁盘驱动器的大小一样,这里有一些混淆。
“比较结果与基准”,做什么?
FLOPS意味着你需要
1)每个工作单位的FLOP。
2)该单位的工作时间。
比方说,你有一些input文件,通过一些循环做了1000次迭代。 循环是一个方便的工作单位。 它被执行了1000次。 这需要一个小时。
循环有一些加法和乘法以及一些除法和平方根。 你可以计算加法,乘法和除法。 你可以在源代码中查看+,*和/。 您可以从编译器中find汇编语言输出,并在那里计算它们。 你可能会得到不同的数字。 哪一个是对的? 问你的老板。
你可以计算平方根,但是你不知道在乘法和加法方面它究竟做了什么。 所以,你必须做一些基准乘法与平方根之类的东西来得到平方根需要多长时间的感觉。
现在你知道你的循环中的FLOPS。 你知道运行1000次的时间。 你知道FLOPS每秒。
然后你看看LINPACK,发现你比较慢。 怎么办? 你的程序不是LINPACK,比LINPACK慢。 赔率真的很好,你的代码会变慢。 除非你的代码是在一个LINPACK的相同年份内编写和优化的,否则你会变慢。
这是另一部分。 你的处理器对各种基准testing都有一些定义的FLOPS评级。 你的algorithm不是其中的一个基准,所以你没有达到基准。 这不好吗? 或者这是不是基准的明显后果?
可行的结果是什么?
对一些基准testing代码进行测量只会告诉你,algorithm不是基准algorithm。 这是一个定局,你会有所不同, 通常比较慢。
显然,对LINPACK的测量结果将是(a)你是不同的,因此(b)你需要优化。
测量对你自己来说只是非常有价值的。 不是一些假设的教学组合,而是你自己的教学组合。 衡量你自己的performance。 做出改变。 看看你的performance – 与你自己相比 – 变好还是变坏。
FLOPS不重要。 重要的是每个工作单位的时间。 你永远不会匹配硬件的devise参数,因为你没有运行你的硬件devise者期望的基准。
LINPACK无关紧要。 重要的是你的代码库和你正在改变性能的变化。
旧的问题,如果受欢迎,回答不完全是伟大的,国际海事组织。
“FLOP”是一个浮点math运算。 “FLOPS”可以表示以下两种情况之一:
- “FLOP”的简单复数(即“操作X需要50 FLOP”)
- 第一种意义上FLOP的比率 (即每秒浮点math运算)
如果从上下文中不清楚的话,通常把前者称为“FLOP”,后者称为“FLOP / s”,通常将其中的哪一个区分开来。
FLOP是所谓的区别于其他types的CPU操作 ,如整数math运算,逻辑运算,按位运算,存储器操作和分支操作,它们具有不同的成本(读取“花费不同的时间长度”)他们。
“FLOP计数”的做法可以追溯到科学计算的最初几天,相对而言,FLOP是非常昂贵的,每个循环需要很多的CPU周期。 例如,一个80387的math协处理器就像一个300乘以一个乘法。 这是在stream水线之前,CPU时钟速度和内存速度之间的差距真正开放之前:内存操作只需要一两个周期,分支(“决策”)同样便宜。 那么,如果你可以消除一个单一的FLOP赞成十几个内存访问,你就获得了一个好处。 如果你可以消除一个单一的FLOP赞成十几个分支,你赚了一笔。 所以, 在过去,计算FLOP并且不用担心内存引用和分支是有意义的,因为FLOP强烈地支配执行时间,因为它们相对于其他types的操作单独非常昂贵。
最近,情况发生了逆转。 FLOP变得非常便宜 – 任何现代英特尔内核每个周期可以执行大约两个FLOP(虽然部门仍然相对昂贵),并且内存访问和分支相对昂贵得多:L1caching命中成本可能是3或4个周期,主要记忆成本150-200。 鉴于这种倒置, 消除FLOP而不是存储器访问将导致收益 ; 事实上,这不太可能。 同样,即使是多余的,“做”FLOP通常也比较便宜,而不是决定是否做。 这与25年前的情况完全相反。
不幸的是,作为algorithm优点的绝对度量,盲FLOP计数的实践在销售date之前一直坚持不懈。 现代科学计算更多的是关于内存带宽pipe理 – 试图让FLOP不断执行数据的执行单元 – 而不是减lessFLOP的数量。 LINPACK (二十年前基本上被LAPACK废除了)引起了我的怀疑,认为你的雇主可能是一所很老的学校,它并没有内化这样一个事实,即build立绩效期望不仅仅是FLOP计算的问题。 如果一个解算器的FLOP数量是另一个FLOP的两倍,那么它的存储访问模式和数据布局要好得多。
所有这一切的结果是计算密集型软件的性能评估变得比以前复杂得多 。 FLOPs已经变得便宜的事实由于记忆操作和分支成本的巨大变化而变得非常复杂。 在评估algorithm时 ,简单的FLOP计算根本不会告知整体性能预期。
也许更好的思考性能预期和评估的方法是由所谓的车顶线模型提供的 ,这远远不够完美,但它的优点是可以考虑浮点和内存带宽问题之间的平衡同时提供更具信息量和洞察力的“2D图片”,可以比较性能测量结果和性能预期。
值得一看。
正如你所说,FLOPS是每秒浮点运算。 例如,如果您只需要一秒的操作(例如加,减,乘或除两个值并返回结果),则您的性能仅为1 FLOPS。 最近的一个CPU很容易实现几GigaFLOPS,即每秒几十亿个浮点运算。
我只是试图尽可能快地去做,而且这需要找出花费的时间,特别是如果有函数调用可以避免的话。
我用一个简单的方法,在运行的时候中断它几次,看看它在做什么。 以下是我发现的一些事情:
-
大部分时间是在计算导数和雅可比matrix的过程中。 大部分时间可以进入math函数调用,如
exp()
,log()
和sqrt()
。 通常这些都是用相同的论点来重复的,并且可以被logging下来。 (巨大的加速。) -
大部分时间花在计算衍生产品上的次数太多,因为整合公差比必要的更严格。 (更快)
-
如果使用隐式积分algorithm(例如DLSODE Gear),因为方程式被认为是僵硬的,那么它们可能不是,可以使用像龙格 – 库塔(Runge-Kutta)这样的方法。 (DVERK)。 (更快)
-
如果模型是线性的(DGPADM),则可以使用matrix指数algorithm。 这对于性能和精度来说是一个巨大的胜利,并且不受硬度的影响。 (方式更快)
-
在调用堆栈上面,可能会有相同的积分重复执行,参数略有不同,从而确定解决scheme相对于这些参数的前向或中心差分梯度。 如果微分方程本身是可微分的,那么可以通过分析得到这些梯度,或者通过用灵敏度方程来增加方程。 这不仅要快得多,而且要精确得多,这样可以加快速度。
您可以查看堆栈的每个级别,作为寻找优化的机会,并且加速将会复合。 然后,当你去到多CPU,假设它是可并行化的,那应该提供它自己的乘法因子。
所以回到FLOPs。 您可以尝试最大化 FLOPs / second
,但是通过在堆栈的所有级别进行优化,还可以将FLOPs / run
最小化 。 无论如何,只要测量它们几乎不会告诉你什么。
你的雇主是对的。
衡量Fortran程序(或任何其他程序,btw)的有效性的唯一方法是根据标准基准testing它,如果存在的话。
而且,关于FLOP,它代表“每秒浮点运算” – 请参阅Wikipedia上的定义 。
我不认为测量FLOPS将是非常有用的。
实现的FLOPS数量将告诉你algorithm保持CPU的繁忙程度,但不会告诉你algorithm本身的性能如何。
您可能会发现两种不同的algorithm,这些algorithm会导致处理器执行相同数量的FLOPS,但在一半的时间内会为您提供所需的结果。
我认为你最好是看一个更高层次的统计数据,比如每单位时间求解微分方程的数量(也就是说algorithm的目的)。
另一方面,测量实现的FLOPS数量可能会帮助您改进algorithm,因为它会告诉您保持CPU的繁忙程度。