基准测试
由于答案中显示了许多不同的方法,并且没有一个答案实际上证明在性能方面有任何优势,因此我尝试自己对它们进行基准测试。我的计划是写一个包含 short 表格的答案和一个明确的答案,哪种方法最快。
不幸的是,事情并没有那么简单。 (从来没有。)似乎舍入公式的性能取决于使用的数据类型、编译器和优化级别。
在一种情况下,从一种方法到另一种方法的速度提高了 7.5 倍。因此,对某些人来说,影响可能很大。
TL;DR
对于long 整数,使用类型转换为float 和std::ceil 的简单版本实际上是最快的。这对我个人来说很有趣,因为我打算将它与size_t 一起使用,它通常定义为unsigned long。
对于普通的ints,这取决于您的优化级别。对于较低级别的@Jwodder 的解决方案表现最好。对于最高级别std::ceil 是最佳级别。除了一个例外:对于 clang/unsigned int 组合,@Jwodder's 仍然更好。
接受答案的解决方案从未真正超越其他两个。但是您应该记住,@Jwodder 的解决方案不适用于否定。
结果在底部。
实现
这里回顾一下我基准测试和比较的四种方法:
template<typename T>
inline T divCeilJwodder(const T& numerator, const T& denominator)
{
return (numerator + denominator - 1) / denominator;
}
template<typename T>
inline T divCeilVoigtModulo(const T& numerator, const T& denominator)
{
return numerator / denominator + (((numerator < 0) ^ (denominator > 0))
&& (numerator%denominator));
}
inline T divCeilVoigtNoModulo(const T& numerator, const T& denominator)
{
T truncated = numerator / denominator;
return truncated + (((numerator < 0) ^ (denominator > 0))
&& (numerator - truncated*denominator));
}
template<typename T>
inline T divCeilTypeCast(const T& numerator, const T& denominator)
{
return (int)std::ceil((double)numerator / denominator);
}
方法
在单个批次中,除法执行 1 亿次。针对编译器/优化级别、使用的数据类型和使用的实现的每种组合计算十个批次。下面显示的值是所有 10 个批次的平均值,以毫秒为单位。给出的错误是standard deviations。
使用的整个源代码可以在here 找到。此外,您可能会发现 this 脚本很有用,它使用不同的编译器标志编译和执行源代码。
整个基准测试是在 i7-7700K 上执行的。使用的编译器版本是 GCC 10.2.0 和 clang 11.0.1。
结果
现在不用多说,结果如下:
DataType Algorithm |
GCC -O0 |
-O1 |
-O2 |
-O3 |
-Os |
-Ofast |
-Og |
clang -O0 |
-O1 |
-O2 |
-O3 |
-Ofast |
-Os |
-Oz |
unsigned |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Jwodder |
264.1 ± 0.9 ? |
175.2 ± 0.9 ? |
153.5 ± 0.7 ? |
175.2 ± 0.5 ? |
153.3 ± 0.5 |
153.4 ± 0.8 |
175.5 ± 0.6 ? |
329.4 ± 1.3 ? |
220.0 ± 1.3 ? |
146.2 ± 0.6 ? |
146.2 ± 0.6 ? |
146.0 ± 0.5 ? |
153.2 ± 0.3 ? |
153.5 ± 0.6 ? |
| VoigtModulo |
528.5 ± 2.5 |
306.5 ± 1.0 |
175.8 ± 0.7 |
175.2 ± 0.5 ? |
175.6 ± 0.7 |
175.4 ± 0.6 |
352.0 ± 1.0 |
588.9 ± 6.4 |
408.7 ± 1.5 |
164.8 ± 1.0 |
164.0 ± 0.4 |
164.1 ± 0.4 |
175.2 ± 0.5 |
175.8 ± 0.9 |
| VoigtNoModulo |
375.3 ± 1.5 |
175.7 ± 1.3 ? |
192.5 ± 1.4 |
197.6 ± 1.9 |
200.6 ± 7.2 |
176.1 ± 1.5 |
197.9 ± 0.5 |
541.0 ± 1.8 |
263.1 ± 0.9 |
186.4 ± 0.6 |
186.4 ± 1.2 |
187.2 ± 1.1 |
197.2 ± 0.8 |
197.1 ± 0.7 |
| TypeCast |
348.5 ± 2.7 |
231.9 ± 3.9 |
234.4 ± 1.3 |
226.6 ± 1.0 |
137.5 ± 0.8 ? |
138.7 ± 1.7 ? |
243.8 ± 1.4 |
591.2 ± 2.4 |
591.3 ± 2.6 |
155.8 ± 1.9 |
155.9 ± 1.6 |
155.9 ± 2.4 |
214.6 ± 1.9 |
213.6 ± 1.1 |
unsigned long |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Jwodder |
658.6 ± 2.5 |
546.3 ± 0.9 |
549.3 ± 1.8 |
549.1 ± 2.8 |
540.6 ± 3.4 |
548.8 ± 1.3 |
486.1 ± 1.1 |
638.1 ± 1.8 |
613.3 ± 2.1 |
190.0 ± 0.8 ? |
182.7 ± 0.5 |
182.4 ± 0.5 |
496.2 ± 1.3 |
554.1 ± 1.0 |
| VoigtModulo |
1,169.0 ± 2.9 |
1,015.9 ± 4.4 |
550.8 ± 2.0 |
504.0 ± 1.4 |
550.3 ± 1.2 |
550.5 ± 1.3 |
1,020.1 ± 2.9 |
1,259.0 ± 9.0 |
1,136.5 ± 4.2 |
187.0 ± 3.4 ? |
199.7 ± 6.1 |
197.6 ± 1.0 |
549.4 ± 1.7 |
506.8 ± 4.4 |
| VoigtNoModulo |
768.1 ± 1.7 |
559.1 ± 1.8 |
534.4 ± 1.6 |
533.7 ± 1.5 |
559.5 ± 1.7 |
534.3 ± 1.5 |
571.5 ± 1.3 |
879.5 ± 10.8 |
617.8 ± 2.1 |
223.4 ± 1.3 |
231.3 ± 1.3 |
231.4 ± 1.1 |
594.6 ± 1.9 |
572.2 ± 0.8 |
| TypeCast |
353.3 ± 2.5 ? |
267.5 ± 1.7 ? |
248.0 ± 1.6 ? |
243.8 ± 1.2 ? |
154.2 ± 0.8 ? |
154.1 ± 1.0 ? |
263.8 ± 1.8 ? |
365.5 ± 1.6 ? |
316.9 ± 1.8 ? |
189.7 ± 2.1 ? |
156.3 ± 1.8 ? |
157.0 ± 2.2 ? |
155.1 ± 0.9 ? |
176.5 ± 1.2 ? |
int |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Jwodder |
307.9 ± 1.3 ? |
175.4 ± 0.9 ? |
175.3 ± 0.5 ? |
175.4 ± 0.6 ? |
175.2 ± 0.5 |
175.1 ± 0.6 |
175.1 ± 0.5 ? |
307.4 ± 1.2 ? |
219.6 ± 0.6 ? |
146.0 ± 0.3 ? |
153.5 ± 0.5 |
153.6 ± 0.8 |
175.4 ± 0.7 ? |
175.2 ± 0.5 ? |
| VoigtModulo |
528.5 ± 1.9 |
351.9 ± 4.6 |
175.3 ± 0.6 ? |
175.2 ± 0.4 ? |
197.1 ± 0.6 |
175.2 ± 0.8 |
373.5 ± 1.1 |
598.7 ± 5.1 |
460.6 ± 1.3 |
175.4 ± 0.4 |
164.3 ± 0.9 |
164.0 ± 0.4 |
176.3 ± 1.6 ? |
460.0 ± 0.8 |
| VoigtNoModulo |
398.0 ± 2.5 |
241.0 ± 0.7 |
199.4 ± 5.1 |
219.2 ± 1.0 |
175.9 ± 1.2 |
197.7 ± 1.2 |
242.9 ± 3.0 |
543.5 ± 2.3 |
350.6 ± 1.0 |
186.6 ± 1.2 |
185.7 ± 0.3 |
186.3 ± 1.1 |
197.1 ± 0.6 |
373.3 ± 1.6 |
| TypeCast |
338.8 ± 4.9 |
228.1 ± 0.9 |
230.3 ± 0.8 |
229.5 ± 9.4 |
153.8 ± 0.4 ? |
138.3 ± 1.0 ? |
241.1 ± 1.1 |
590.0 ± 2.1 |
589.9 ± 0.8 |
155.2 ± 2.4 |
149.4 ± 1.6 ? |
148.4 ± 1.2 ? |
214.6 ± 2.2 |
211.7 ± 1.6 |
long |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Jwodder |
758.1 ± 1.8 |
600.6 ± 0.9 |
601.5 ± 2.2 |
601.5 ± 2.8 |
581.2 ± 1.9 |
600.6 ± 1.8 |
586.3 ± 3.6 |
745.9 ± 3.6 |
685.8 ± 2.2 |
183.1 ± 1.0 |
182.5 ± 0.5 |
182.6 ± 0.6 |
553.2 ± 1.5 |
488.0 ± 0.8 |
| VoigtModulo |
1,360.8 ± 6.1 |
1,202.0 ± 2.1 |
600.0 ± 2.4 |
600.0 ± 3.0 |
607.0 ± 6.8 |
599.0 ± 1.6 |
1,187.2 ± 2.6 |
1,439.6 ± 6.7 |
1,346.5 ± 2.9 |
197.9 ± 0.7 |
208.2 ± 0.6 |
208.0 ± 0.4 |
548.9 ± 1.4 |
1,326.4 ± 3.0 |
| VoigtNoModulo |
844.5 ± 6.9 |
647.3 ± 1.3 |
628.9 ± 1.8 |
627.9 ± 1.6 |
629.1 ± 2.4 |
629.6 ± 4.4 |
668.2 ± 2.7 |
1,019.5 ± 3.2 |
715.1 ± 8.2 |
224.3 ± 4.8 |
219.0 ± 1.0 |
219.0 ± 0.6 |
561.7 ± 2.5 |
769.4 ± 9.3 |
| TypeCast |
366.1 ± 0.8 ? |
246.2 ± 1.1 ? |
245.3 ± 1.8 ? |
244.6 ± 1.1 ? |
154.6 ± 1.6 ? |
154.3 ± 0.5 ? |
257.4 ± 1.5 ? |
591.8 ± 4.1 ? |
590.4 ± 1.3 ? |
154.5 ± 1.3 ? |
135.4 ± 8.3 ? |
132.9 ± 0.7 ? |
132.8 ± 1.2 ? |
177.4 ± 2.3 ? |
现在我终于可以继续我的生活了:P