C++ 如何处理代码中的优化

C++ 如何处理代码中的优化,c++,c,optimization,C++,C,Optimization,我目前正在为一些代码编写各种优化。这些优化中的每一个都会对代码效率(希望如此)以及源代码产生很大的影响。但是,我想保留启用和禁用其中任何一个用于基准测试的可能性 我传统上使用#ifdef OPTIM_X_ENABLE/#else/#endif方法,但代码很快变得难以维护 还可以为每个优化创建SCM分支。在您想要启用或禁用多个优化之前,代码可读性要好得多 有没有其他更好的优化方法 编辑: 某些优化无法同时工作。我可能需要禁用一个旧的优化来测试一个新的优化,看看我应该保留哪一个 我会为优化创建一个分

我目前正在为一些代码编写各种优化。这些优化中的每一个都会对代码效率(希望如此)以及源代码产生很大的影响。但是,我想保留启用和禁用其中任何一个用于基准测试的可能性

我传统上使用
#ifdef OPTIM_X_ENABLE/#else/#endif
方法,但代码很快变得难以维护

还可以为每个优化创建SCM分支。在您想要启用或禁用多个优化之前,代码可读性要好得多

有没有其他更好的优化方法

编辑:
某些优化无法同时工作。我可能需要禁用一个旧的优化来测试一个新的优化,看看我应该保留哪一个

我会为优化创建一个分支,对其进行基准测试,直到您知道它有显著的改进,然后简单地将其合并回主干。一旦它回到后备箱上,我就不会为它操心了;一旦你知道它是好的,你为什么要禁用它?如果希望能够回滚特定的更改,则始终具有存储库历史记录。

我将在类级别(或C的文件级别)工作,并将所有不同的版本嵌入到同一个工作软件中(无ifdef),并在运行时通过一些配置文件或命令行选项选择一个实现或另一个实现。 这应该很容易,因为优化不应该改变内部API级别的任何内容

另一种方法,如果你正在使用C++,可以实例化模板,避免复制高级别代码或在运行时选择分支(即使这通常是一个可接受的选项,但这里的某些开关通常并不是一个大问题)。 最终,各种优化的后端都可以转换为库

单元测试应该能够在不修改每个实现变量的情况下工作


我的基本原理是,嵌入每一个变体都会改变软件的大小,这很少是一个问题。这种方法还有其他好处:您可以轻松地处理不断变化的环境。某些操作系统或某些硬件的优化可能不是一对一的。在许多情况下,在运行时选择最佳版本甚至很容易

有很多方法可以选择要执行的代码的哪一部分。根据我的经验,使用预处理器的条件包含通常是最难维护的。所以,如果可以的话,尽量减少这一点。您可以在不同的功能中分离功能(优化、未优化)。然后根据标志有条件地调用函数。或者,您可以创建继承层次结构并使用虚拟分派。当然,这取决于你的具体情况。也许如果你能更详细地描述它,你会得到更好的答案

然而,这里有一个简单的方法可能适合您:创建两组函数(或类,无论您使用哪种范式)。将函数分成不同的名称空间,一个用于优化代码,另一个用于可读代码。然后通过有条件地使用它们来选择要使用的集合。大概是这样的:

#include <iostream>
#include "optimized.h"
#include "readable.h"

#define USE_OPTIMIZED

#if defined(USE_OPTIMIZED)
using namespace optimized;
#else
using namespace readable;
#endif

int main()
{
   f();
}
readable.h
中:

namespace optimized
{
   void f() { std::cout << "optimized selected" << std::endl; }
}
namespace readable
{
   void f() { std::cout << "readable selected" << std::endl; }
}
#include "optimized.h"
#include "readable.h"

#define USE_OPTIMIZED

#if defined(USE_OPTIMIZED)
using namespace optimized;
#else
using namespace readable;
#endif
现在,只需包含此头并进一步最小化潜在的预处理器使用。顺便说一句,通常的割台/cpp分离仍应进行


祝你好运

我很困惑。为什么不找出每个性能问题所在,修复它,然后继续

您可能有两个(三个或更多)版本的功能,您可以使用以下名称进行优化: 功能 函数优化 它们具有相同的参数并返回相同的结果

然后,您可以在som标头中定义选择器,如下所示:

 #if OPTIM_X_ENABLE
 #define OPT(f) f##_optimized
 #else
 #define OPT(f) f
 #endif
然后将具有优化变量的函数调用为OPT(函数)(参数,参数…)。这种方法不是很美,但它确实如此

您可以进一步使用重新定义所有优化函数的名称:

 #if OPTIM_X_ENABLE
 #define foo foo_optimized
 #define bar bar_optimized
 ...
 #endif
并保持呼叫者代码不变。预处理器为您进行函数替换。我最喜欢它,因为它在每个函数(以及每个数据类型和每个变量)粒度上透明地工作,这在大多数情况下对我来说已经足够了


更奇特的方法是为未优化和优化的代码创建单独的.c文件,并只编译其中一个。它们可能有相同的名称,但路径不同,所以可以通过在命令行中更改单个选项来进行切换。

听起来很可怕:)为什么要禁用优化?要么它们工作,并产生影响,然后它们应该成为代码库的一部分,要么它们没有效果,然后启用它们就没有意义了。正如前面所述,尝试这样做很奇怪。这些是特定于平台的优化吗?您是否希望确保保留一些算法的安全版本,以防在优化代码中发现错误?或者,您是否希望保留易于理解的代码以用于文档编制。这种方法的问题在于,如果您正在优化(比如)紧密内部循环的主体,那么在每次迭代中,您要么会有条件地分支到两个实现中的每一个,从而产生开销,或者你最终复制了更高级别的代码。@Oli Charlesworth:你是对的,这是这个解决方案的极限,我相应地更新了我的答案。然而,实际上很少遇到这种情况。如果时间紧迫,因为这可能是一个问题,你可能应该考虑重构内环和调用者,因为新的可能的优化经常出现这样做。换句话说,如果这真的是一个问题,那么您可能在错误的级别上进行了优化。关于这个问题还有另一个非常有趣的答案,所以,我将再次尝试找到它以提供链接。@Oli Charlesworth:好的,我找到了。这个答案是我最喜欢的答案之一。:-)这种方法也有其局限性。如果您想针对不同的p进行优化,该怎么办