【问题标题】:How really distinguish compile time and run time information?如何真正区分编译时和运行时信息?
【发布时间】:2021-06-06 06:54:21
【问题描述】:

这个问题可能看起来很宽泛,但实际上并非如此。
更具体地说,如果我们使用模板,我们如何区分什么是编译时信息和运行时信息?

我正在观看有关优化和 HFT 系统的 CppCon 视频,并遇到了这个示例。如果您不熟悉高频交易系统,并且洞察力是它们确实试图从基准测试中挤出最后几纳秒,通常会违反经典的 OOD 原则以获取性能。

我想详细说明的例子如下:

template<Side T>
void Strategy<T>::run()
{
    const float orderPrice = calcPrice(fairValue, credit);
    //....
    sendOrder(orderPrice);
}

template<>
float Strategy<Side::buy>::calcPrice(float value, float credit)
{
    return value - credit;
}

template<>
float Strategy<Side::sell>::calcPrice(flaot value, float credit)
{
    return value + credit;
}

根据作者的说法,这个例子说明了一种避免运行时 if-else 分支的经典方法。
但是在编译的时候,我们真的不知道是要买还是要cell对吧?在运行期间根据市场走势做出决定。
有人可以解释一下运行时和编译时之间的联系,具体来说,我们如何根据运行时信息创建编译时分支?

【问题讨论】:

    标签: c++ templates compilation metaprogramming


    【解决方案1】:

    Strategy 专门用于buysell 情况。因此,一旦您决定是购买还是出售,您就可以使用其中一个,并且类方法中不再有分支。它本质上是生成 2 个代码路径,你可以用一个分支选择其中一个:

    if (buying) {
      Strategy<Side::buy> strat;
      strat.run();
    } else {
      Strategy<Side::sell> strat;
      strat.run();
    }
    

    【讨论】:

      【解决方案2】:

      您在一般原则上是对的:在编译时,您不知道是卖还是买。这将需要一个 if 语句。

      但是,当用于控制买/卖的单个 if 语句控制两个大的相似代码块时,这里使用的技术仍然有用。您现在可以显式地写出这些块(代码重复),只写一次,但对两个块会发散的所有部分重复 if 语句(慢),或者使用模板让编译器为您生成两个代码块.

      我在自己的代码库中有一个更好的示例,我在其中使用外部开关来选择 7 个模板实例化之一。每个模板实例化都是一个包含数百个元素的循环,外部的开关意味着我在循环内没有开关。当然,我有 7 个模板实例化,但 RAM 很便宜。

      【讨论】:

        【解决方案3】:

        对于您展示的这个简化示例,它可能没有太大区别。

        但是对于 HFT,您有一个任务是出售或购买,并且该任务的所有操作都应该以尽可能短的延迟完成。并且您希望针对这些任务中的每一项都获得最佳优化。

        这两个代码流在许多方面可能相似。但是,如果您有一个更大的代码流,您将有多个 if 条件来检查您是卖出还是买入,那么您有两种可能性:

        1. 您可以希望编译器的优化器将创建两个不同的代码流,一个用于销售,一个用于购买,并减少分支可能性和延迟。一个好的编译器可能确实能够做到这一点,但不能保证这一点,并且对该代码进行一些更改可能会导致编译器由于某种原因停止进行优化。

        2. 如图所示创建一个使用模板的构造。这将保证在您决定要执行哪些任务时,您只有一个检查 sell 和一个检查 buy。而且您不需要依赖编译器为您进行优化,而且您仍然可以防止源代码中的代码重复。

        2. 具有额外的好处,即编译器可能能够进行更进一步的优化,例如内联、指令重新排序……因为您删除了对 buy/sell 的任何额外检查做了一次检查。而且减少分支的可能性也可以帮助CPU的分支预测。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-05-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-20
          • 1970-01-01
          • 2021-07-21
          相关资源
          最近更新 更多