【发布时间】:2018-10-03 20:33:10
【问题描述】:
有人可以帮助我了解使用 asm 块进行 unsigned long long 乘法在性能方面的好处。它与竞争性编程优化有关。我猜它使乘法更快,但我实际上无法理解代码。
const int md = 998244353;
inline int mul(int a, int b)
{
#if !defined(_WIN32) || defined(_WIN64)
return (int) ((long long) a * b % md);
#endif
unsigned long long x = (long long) a * b;
unsigned xh = (unsigned) (x >> 32), xl = (unsigned) x, d, m;
asm(
"divl %4; \n\t"
: "=a" (d), "=d" (m)
: "d" (xh), "a" (xl), "r" (md)
);
return m;
}
【问题讨论】:
-
不管它是如何工作的,这段代码在使用现代编译器时很可能已经过时了,因为它们应该从原始版本生成更好或可比较的输出。
-
专业提示:编译器是由很多真正聪明的人编写的。如果你给他们明显的代码,他们会很好地为你提供最好的机器代码。这意味着可理解的代码通常会变成高性能代码。
-
@BartekBanachewicz:那是因为您禁用了优化!有关来自 clang 和 gcc
-O3的更好代码,请参阅 godbolt.org/z/qtQkxc。所有现代编译器都知道如何使用乘法逆进行除以编译时常数,但 gcc 是唯一一个即使在-O0, IIRC 也这样做的编译器。 Why does GCC use multiplication by a strange number in implementing integer division? -
@NathanOliver:如果那是真的!编译器通常会生成好的代码,但几乎不可能是最好的。
标签: c++ assembly x86 inline-assembly integer-division