c++ - 多线程:为什么两个程序比一个好?

  显示原文与译文双语对照的内容
0 0

Shortly有关我的问题:

我的电脑有2 个插槽的AMD Opteron 6272和64GB RAM 。

我运行一个多线程程序在所有32个核心和获取速度15%相较少情况下当我运行程序,每个在一台16核2 套接字。

如何让一个程序两个版本一样快的程序


详情:

我有一个大的系统,并希望完全加载所有32个核心的任务数量。 所以我收拾了1000中的任务组。 这么一个组织需要评价120Mb输入数据,大概需要10秒才能完成在一个内核上。 进行测试所使用ITBBs我这么多年来将这些组32次, parallel_for循环32个核心之间分发任务。

我使用 pthread_setaffinity_np这样可以确保系统不会造成我的内核线程之间跳转。 并且,这样可以确保所有内核都是用consequtively 。

我使用 mlockall(MCL_FUTURE)这样可以确保系统不会造成我的内存插槽之间跳转。

接下来的代码如下所示:

  void operator()(const blocked_range<size_t> &range) const
  {
    for(unsigned int i = range.begin(); i != range.end(); ++i){

      pthread_t I = pthread_self();
      int s;
      cpu_set_t cpuset;
      pthread_t thread = I;
      CPU_ZERO(&cpuset);
      CPU_SET(threadNumberToCpuMap[i], &cpuset);
      s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);

      mlockall(MCL_FUTURE); // lock virtual memory to stay at physical address where it was allocated

      TaskManager manager;
      for (int j = 0; j < fNTasksPerThr; j++){
        manager.SetData( &(InpData->fInput[j]) );
        manager.Run();
      }
    }
  }

只有计算时间对我来说很重要所以我准备输入数据放在单独的 parallel_for循环。 并不包括准备时间在时间测量。

  void operator()(const blocked_range<size_t> &range) const
  {
    for(unsigned int i = range.begin(); i != range.end(); ++i){

      pthread_t I = pthread_self();
      int s;
      cpu_set_t cpuset;
      pthread_t thread = I;
      CPU_ZERO(&cpuset);
      CPU_SET(threadNumberToCpuMap[i], &cpuset);
      s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);

      mlockall(MCL_FUTURE); // lock virtual memory to stay at physical address where it was allocated
      InpData[i].fInput = new ProgramInputData[fNTasksPerThr];

      for(int j=0; j<fNTasksPerThr; j++){
        InpData[i].fInput[j] = InpDataPerThread.fInput[j];
      }
    }
  }

每秒运行所有这些在32个内核和现在我看到~1600任务的速度。

然后我创建两个版本的程序,然后用 tasksetpthread首先,确保万无一失的第二个上第一个插槽和第二个插槽16内核上运行。 我完成一个任务使用简单的相邻 &命令在shell :

program1 & program2 &

每一个程序可以快速提高~900 tasks/s 。 这种情况总共是>1800 tasks/s,这是15%多个程序版本。

我错过了什么

我认为,只可能是线程的集合,而我的问题是在库加载到内存中。 才能使这成为一个问题? 可以复制数据,以便库) 就分别在两个套接字?

时间: 原作者:

0 0

我猜想是STL/boost内存分配的内存为集合等分散到numa节点希望的,因为他们不是numa aware和你的程序中的线程运行在每个节点。

自定义的分配器在STL/boost的东西全部都要使用可以帮助( 但很可能的一项大工程) 。

原作者:
0 0

你可能会遭受身体迸发力量伪共享的cache : http://en .wikipedia .org/wiki/False_sharing

你的线程可能共享访问相同的数据结构通过block_range参考。 如果速度是你所需,你可能希望将一个副本传递给每个线程。 如果数据太大将其调整到调用堆栈可以动态分配的副本不同的缓存中每个范围段( 我如果不包含。 只需确保他们足够远appart ) 。

或者也许我需要查看其余的代码来更好地了解我们在干嘛

...