0

我对在 Opensuse Linux 上使用 gcc 4.7.2 的以下代码的结果感到惊讶:

#include <cmath>
#include <chrono>
#include <cstdlib>
#include <vector>
#include <chrono>
#include <iostream>
#include <future>

int main(void)
{
  const long N = 10*1000*1000;
  std::vector<double> array(N);
  for (auto& i : array)
    i = rand()/333.;

  std::chrono::time_point<std::chrono::system_clock> start, end;
  start = std::chrono::system_clock::now();
  for (auto& i : array)
    pow(i,i);
  end = std::chrono::system_clock::now();
  std::chrono::duration<double> elapsed_seconds = end-start;
  std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";

  start = std::chrono::system_clock::now();
  for (auto& i : array)
    std::packaged_task<double(double,double)> myTask(pow);
  elapsed_seconds = std::chrono::system_clock::now()-start;
  std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";

  start = std::chrono::system_clock::now();
  for (auto& i : array)
    std::packaged_task<double()> myTask(std::bind(pow,i,i));
  elapsed_seconds = std::chrono::system_clock::now()-start;
  std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";

  return 0;
}

结果看起来像这样(并且在运行中相当一致):

elapsed time: 0.694315s
elapsed time: 6.49907s
elapsed time: 8.42619s

如果我正确地解释结果,仅仅创建一个std::packaged_task(甚至不执行它或存储它的参数)已经比executing pow. 这是一个有效的结论吗?

为什么会这样?

这是偶然的gcc特定的吗?

4

1 回答 1

3

您没有计时 a 的执行packaged_task,只有它的创建。

std::packaged_task<double(double,double)> myTask(pow);

这不会执行myTask,只会创建它。理想情况下,你不应该测量这个,你应该测量myTask(i, i),我通过将你的程序更改为以下来做到这一点(我用 删除了测量std::bind)。

结果比您测量的要差:

timing raw
elapsed time: 0.578244s

timing ptask
elapsed time: 20.7379s

我猜packaged_tasks 不适合可重复的小任务,开销肯定大于任务本身。我对此的解读是,您应该将它们用于多任务代码,该任务花费的时间比调用和同步packaged_task.

如果您不是多任务处理,我认为将函数调用包装在准备好使用同步原语进行多线程处理的类中是没有意义的,可悲的是,它们不是免费的。

作为记录,这是我使用的:

#include <cmath>
#include <chrono>
#include <cstdlib>
#include <vector>
#include <chrono>
#include <iostream>
#include <future>
#include <thread>

int main(void)
{
  const long N = 10*1000*1000;
  std::vector<double> array(N);
  for (auto& i : array)
    i = rand()/333.;

  std::cout << "timing raw" << std::endl;
  std::chrono::time_point<std::chrono::system_clock> start, end;
  start = std::chrono::system_clock::now();
  for (auto& i : array)
    pow(i,i);
  end = std::chrono::system_clock::now();
  std::chrono::duration<double> elapsed_seconds = end-start;
  std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n\n";

  std::cout << "timing ptask" << std::endl;
  start = std::chrono::system_clock::now();
  std::packaged_task<double(double,double)> myTask(pow);
  for (auto& i : array)
  {
      myTask(i, i);
      myTask.get_future().wait();
      myTask.reset();
  }
  elapsed_seconds = std::chrono::system_clock::now()-start;
  std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n\n";
  return 0;
}
于 2015-05-25T23:08:32.637 回答