首页 > 解决方案 > 带有 std::async 的函数在 Linux 上不使用多个内核

问题描述

我正在查看CppCon2019 的 Daniel Hanson的会议。它是关于在量化金融中应用现代 C++。关键思想之一是异步运行股票价格生成器,从而可以大大加快蒙特卡洛过程。

这个功能特别引起了我的注意。它在 Visual Studio 中按预期工作,但无法在我的 Linux 机器上异步运行。

void MCEuroOptPricer::computePriceAsync_() {
  // a callable object that returns a `std::vector<double>` when called
  EquityPriceGenerator epg(spot_, numTimeSteps_, timeToExpiry_, riskFreeRate_,
                           volatility_);
  // fills `seeds_` (a std::vector<int>) with `std::iota`
  generateSeeds_();

  std::vector<std::future<std::vector<double>>> futures;
  futures.reserve(numScenarios_);
  for (auto &seed : seeds_) {
    futures.push_back(std::async(epg, seed));
  }

  std::vector<double> discountedPayoffs;
  discountedPayoffs.reserve(numScenarios_);
  for (auto &future : futures) {
    double terminalPrice = future.get().back();
    double payoff = payoff_(terminalPrice);
    discountedPayoffs.push_back(discFactor_ * payoff);
  }

  double numScens = static_cast<double>(numScenarios_);
  price_ =
      quantity_ * (1.0 / numScens) *
      std::accumulate(discountedPayoffs.begin(), discountedPayoffs.end(), 0.0);
}

我正在使用clang++ -std=c++17 -O3. 此并行版本的运行速度甚至比非并行版本还要慢。根据 htop,它没有使用多个内核。我试图打电话std::asyncstd::launch::async但它也没有帮助。是因为我缺少一些编译器选项还是 Visual Studio 的编译器正在应用一些我不知道的优化?如何让这个函数在 Linux 上异步运行?

不是 CS 专业的,所以我可能只是遗漏了一些明显的东西。任何帮助是极大的赞赏。

更新:事实证明,当前std::async是在 Windows 上池化的,而不是在类 UNIX 系统上。Dmitry Danilov 的这篇文章详细解释了这一点。

我设法通过涉及boost/asio/thread_pool.hpp.

void MCEuroOptPricer::computePriceWithPool_() {
  EquityPriceGenerator epg(spot_, numTimeSteps_, timeToExpiry_, riskFreeRate_,
                           volatility_);
  generateSeeds_();

  std::vector<double> discountedPayoffs;
  discountedPayoffs.reserve(numScenarios_);

  std::mutex mtx; // avoid data races when writing into the vector
  boost::asio::thread_pool pool(get_nprocs());
  for (auto &seed : seeds_) {
    boost::asio::post(pool, [&]() {
      double terminalPrice = (epg(seed)).back();
      double payoff = payoff_(terminalPrice);
      mtx.lock();
      discountedPayoffs.push_back(discFactor_ * payoff);
      mtx.unlock();
    });
  }
  pool.join();

  double numScens = static_cast<double>(numScenarios_);
  price_ =
      quantity_ * (1.0 / numScens) *
      std::accumulate(discountedPayoffs.begin(), discountedPayoffs.end(), 0.0);
}

标签: c++quantitative-financestdasync

解决方案


推荐阅读