Fra*_*lić 6 c++ optimization reference
请考虑以下代码:
Matrix4x4 perspective(const ViewFrustum &frustum) {
float l = frustum.l;
float r = frustum.r;
float b = frustum.b;
float t = frustum.t;
float n = frustum.n;
float f = frustum.f;
return {
{ 2 * n / (r - l), 0, (r + l) / (r - l), 0 },
{ 0, 2 * n / (t - b), (t + b) / (t - b), 0 },
{ 0, 0, -((f + n) / (f - n)), -(2 * n * f / (f - n)) },
{ 0, 0, -1, 0 }
};
}
Run Code Online (Sandbox Code Playgroud)
为了提高构造矩阵的可读性,我必须从截头结构中复制值,或者引用它们.但是,我实际上也不需要复制或间接.
是否有可能在编译时解决某种"引用",有点像符号链接.它会产生与以下相同的效果:
Matrix4x4 perspective(const ViewFrustum &frustum) {
#define l frustum.l;
#define r frustum.r;
#define b frustum.b;
#define t frustum.t;
#define n frustum.n;
#define f frustum.f;
return {
{ 2 * n / (r - l), 0, (r + l) / (r - l), 0 },
{ 0, 2 * n / (t - b), (t + b) / (t - b), 0 },
{ 0, 0, -((f + n) / (f - n)), -(2 * n * f / (f - n)) },
{ 0, 0, -1, 0 }
};
#undef l
#undef r
#undef b
#undef t
#undef n
#undef f
}
Run Code Online (Sandbox Code Playgroud)
没有预处理器(或者它可以接受吗?).我想这不是真的需要,或者在这种特殊情况下可以通过直接将这6个值参数化为函数来避免(虽然这样调用函数会有点恼人 - 但即便如此,我也可以内联代理功能).
但我只是想知道这是否在某种程度上是可能的?我找不到类似的东西.我认为在本地缩短将被大量使用的描述性名称会变得非常方便,而不必丢失原始名称.
Sam*_*hik 12
嗯,这就是C++引用的用途:
const float &l = frustum.l;
const float &r = frustum.r;
const float &b = frustum.b;
const float &t = frustum.t;
const float &n = frustum.n;
const float &f = frustum.f;
Run Code Online (Sandbox Code Playgroud)
大多数现代编译器将优化引用,并frustum通过在编译时解析引用,在下面的表达式中逐字使用对象中的值.
小智 11
强制性免责声明:不要过早优化.
让我比较你的天真perspective功能,包含
float l = frustum.l;
float r = frustum.r;
float b = frustum.b;
float t = frustum.t;
float n = frustum.n;
float f = frustum.f;
Run Code Online (Sandbox Code Playgroud)
随着define's和@Sam Varshavchik解决方案的参考.
我们假设我们的编译器正在优化,并且至少优化得体.
所有三个版本的汇编输出:https://godbolt.org/g/G06Bx8.
您可以注意到引用和定义版本完全相同 - 正如预期的那样.但天真有很大不同.它首先加载内存中的所有值:
movss (%rdi), %xmm2 # xmm2 = mem[0],zero,zero,zero
movss 4(%rdi), %xmm1 # xmm1 = mem[0],zero,zero,zero
movss 8(%rdi), %xmm0 # xmm0 = mem[0],zero,zero,zero
movss %xmm0, 12(%rsp) # 4-byte Spill
movss 12(%rdi), %xmm0 # xmm0 = mem[0],zero,zero,zero
movss %xmm0, 8(%rsp) # 4-byte Spill
movss 16(%rdi), %xmm3 # xmm3 = mem[0],zero,zero,zero
movaps %xmm3, 16(%rsp) # 16-byte Spill
movss 20(%rdi), %xmm0
Run Code Online (Sandbox Code Playgroud)
然后再也不会引用%rdi(frustrum)内存.另一方面,引用和定义版本在需要时加载值.
发生这种情况是因为Vector4构造函数的实现对优化器是隐藏的,并且它不能假设构造函数不会修改frustrum,因此它必须插入加载,即使这样的加载是多余的.
因此,在某些情况下,天真版本甚至比"优化版本" 更快.