我只是要求这个试图了解我花了 24 小时试图解决的问题。
我的系统:Ubuntu 12.04.2,Matlab R2011a,它们都是 64 位,基于 Nehalem 的 Intel Xeon 处理器。
问题很简单,Matlab 允许基于 OpenMP 的程序利用启用了超线程的所有 CPU 内核,但不允许 TBB 使用相同的 CPU 内核。
运行 TBB 时,我只能启动 4 个线程,即使我将 maxNumCompThreads 更改为 8。而使用 OpenMP,我可以使用我想要的所有线程。如果没有超线程,TBB 和 OpenMP 当然会使用所有 4 个内核。
我了解超线程,并且它是虚拟的,但 matlab 的限制实际上确实会导致性能下降(额外的参考)。
我使用 2 个程序测试了这个问题,一个简单的 for 循环
#pragma omp parallel for
以及另一个基于 tbb 示例代码的非常简单的循环。
tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred);
tbb::parallel_for_each(tasks.begin(),tasks.end(),invoker<mytask>());
并用 matlab mexFunction 将它们都包裹起来。
有人对此有解释吗?允许matlab节流TBB但不允许OpenMP节流的线程创建方法或结构是否存在固有差异?
参考代码:
开放式MP:
#include "mex.h"
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ){
threadCount = 100000;
#pragma omp parallel for
for(int globalId = 0; globalId < threadCount ; globalId++)
{
for(long i=0;i<1000000000L;++i) {} // Deliberately run slow
}
}
待定:
#include "tbb/parallel_for_each.h"
#include "tbb/task_scheduler_init.h"
#include <iostream>
#include <vector>
#include "mex.h"
struct mytask {
mytask(size_t n)
:_n(n)
{}
void operator()() {
for (long i=0;i<1000000000L;++i) {} // Deliberately run slow
std::cerr << "[" << _n << "]";
}
size_t _n;
};
template <typename T> struct invoker {
void operator()(T& it) const {it();}
};
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const
mxArray* prhs[]) {
tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); // Automatic number of threads
std::vector<mytask> tasks;
for (int i=0;i<10000;++i)
tasks.push_back(mytask(i));
tbb::parallel_for_each(tasks.begin(),tasks.end(),invoker<mytask>());
}