到处使用策略而不是条件是否值得(花费 运行 时间检查编译时间)?
Is it worth it to use policies instead of conditions everywhere (taking run time checking to compile time)?
假设程序中有一个条件:
void foo(bool condition)
{
.... a lot of work....
if (condition)
something1;
else
something2;
.... a lot of work....
}
如果在编译时,在每次调用 foo() 时我们知道我们需要 something1 或 something2,我们可以将程序更改为:
template <bool condition>
void foo()
{
.... a lot of work....
SomePolicy<condition>::do_something();
.... a lot of work....
}
template <bool Condition>
class SomePolicy
{
public:
static void do_something()
{
something1;
}
};
template <>
class SomePolicy<false>
{
public:
static void do_something()
{
something2;
}
};
因此,通过调用 foo<true>
或 foo<false>.
在编译时花费 运行 时间检查是否值得在任何地方都这样做并摆脱某些条件(可能会提高管道性能)?除了代码有点难看,还有什么缺点吗?
P.S。问题是我们不想复制所有 foo
的代码并在不同的地方调用 foo1 和 foo2。
我认为在编译器优化您的语句后,它最终会得到大致相同的代码。您必须衡量您的性能才能为您的编译器获得准确的答案。
Is there any disadvantage of this besides a little ugly code?
您的代码可读性稍差,有什么好处?您已将条件检查从 run-time 移至编译时,但您是否首先分析代码并确定这些检查在热路径上?
您是否需要编写额外的测试来解释您的重构?
通过重构的方式,您将一些逻辑从需要的地方移开,并可能允许其他人(错误地)使用它。
模板通常会增加编译时间。如果你有成千上万的这样的检查,它可能是不平凡的。
那么问题来了,值得吗?大概。通常将计算从 run-time 移动到编译时间 = 快乐的最终用户。但是,如果它面临着更多错误的风险和更大、可读性更差的代码库,而性能提升可以忽略不计,那么您可能需要三思而后行。
Is this worthy to do everywhere and get rid of some conditions (probably will increase pipeline performance)?
不,因为流水线停顿不是瓶颈无处不在。它 可能 值得在您测量到由指令之间的长依赖链引起的瓶颈的热点处执行此操作。 "a lot of work" 中间的单个分支很少对性能产生重大影响。
Is there any disadvantage of this besides a little ugly code?
它限制了在编译时检查的条件,而不是在运行时。在 运行 时具有可变输入的程序通常更通用。
正如您在评论中指出的那样,您确实可以使用所描述的策略将多个 运行 时间检查减少为一个。但是生成所有(显然很大,因为它们做了很多工作)函数两次,无处不在 会导致可执行文件大小显着增长,这是不受欢迎的 side-effect.
此外,它会强制您使用模板,这会强制实现在 header 中。如果你在整个代码中都这样做,那么你的大部分代码将在 headers 中实现,并且当实现被修改时,这将导致大量的重新编译。这在大项目中是一个问题。
假设程序中有一个条件:
void foo(bool condition)
{
.... a lot of work....
if (condition)
something1;
else
something2;
.... a lot of work....
}
如果在编译时,在每次调用 foo() 时我们知道我们需要 something1 或 something2,我们可以将程序更改为:
template <bool condition>
void foo()
{
.... a lot of work....
SomePolicy<condition>::do_something();
.... a lot of work....
}
template <bool Condition>
class SomePolicy
{
public:
static void do_something()
{
something1;
}
};
template <>
class SomePolicy<false>
{
public:
static void do_something()
{
something2;
}
};
因此,通过调用 foo<true>
或 foo<false>.
在编译时花费 运行 时间检查是否值得在任何地方都这样做并摆脱某些条件(可能会提高管道性能)?除了代码有点难看,还有什么缺点吗?
P.S。问题是我们不想复制所有 foo
的代码并在不同的地方调用 foo1 和 foo2。
我认为在编译器优化您的语句后,它最终会得到大致相同的代码。您必须衡量您的性能才能为您的编译器获得准确的答案。
Is there any disadvantage of this besides a little ugly code?
您的代码可读性稍差,有什么好处?您已将条件检查从 run-time 移至编译时,但您是否首先分析代码并确定这些检查在热路径上?
您是否需要编写额外的测试来解释您的重构?
通过重构的方式,您将一些逻辑从需要的地方移开,并可能允许其他人(错误地)使用它。
模板通常会增加编译时间。如果你有成千上万的这样的检查,它可能是不平凡的。
那么问题来了,值得吗?大概。通常将计算从 run-time 移动到编译时间 = 快乐的最终用户。但是,如果它面临着更多错误的风险和更大、可读性更差的代码库,而性能提升可以忽略不计,那么您可能需要三思而后行。
Is this worthy to do everywhere and get rid of some conditions (probably will increase pipeline performance)?
不,因为流水线停顿不是瓶颈无处不在。它 可能 值得在您测量到由指令之间的长依赖链引起的瓶颈的热点处执行此操作。 "a lot of work" 中间的单个分支很少对性能产生重大影响。
Is there any disadvantage of this besides a little ugly code?
它限制了在编译时检查的条件,而不是在运行时。在 运行 时具有可变输入的程序通常更通用。
正如您在评论中指出的那样,您确实可以使用所描述的策略将多个 运行 时间检查减少为一个。但是生成所有(显然很大,因为它们做了很多工作)函数两次,无处不在 会导致可执行文件大小显着增长,这是不受欢迎的 side-effect.
此外,它会强制您使用模板,这会强制实现在 header 中。如果你在整个代码中都这样做,那么你的大部分代码将在 headers 中实现,并且当实现被修改时,这将导致大量的重新编译。这在大项目中是一个问题。