我打算开始为一个跨平台项目"玩"基于任务的并行性.我想使用英特尔线程构建模块.我从Windows和Visual Studio开始.
因为我只是想要原型,我正在考虑只在Windows上"玩",然后有足够的知识在所有兼容平台上使用该库.
我了解到,自VS2010以来,Microsoft提供了一个类似的库,并行处理库,它具有(几乎)与英特尔TBB相同的接口.
一些消息来源建议,包括TBB的团队博客,他们一起构建它,并且它是相同的库.
然而,它并不是真正明确的,因为它经常表明两个库之间存在细微差别.
那么,如果有的话,这些差异是什么?我应该直接与去年稳定该局启动或者是低风险的原型与微软PPL只是玩,跨平台的"真实"的项目上使用该局?
我有一个算法将拜耳图像通道转换为RGB.在我的实现中,我有一个嵌套for
循环,它遍历拜耳通道,从拜耳索引计算rgb索引,然后从拜耳通道设置该像素的值.这里要注意的主要事实是每个像素可以独立于其他像素计算(不依赖于先前的计算),因此该算法是并行化的自然候选者.但是,计算依赖于某些预设数组,所有线程将在同一时间访问但不会更改.
然而,当我尝试将主要for
与MS 并行化时,我的cuncurrency::parallel_for
性能没有提升.事实上,对于在4核CPU上运行的大小为3264X2540的输入,非并行化版本在~34ms内运行,并行化版本运行在~69ms(平均超过10次运行).我确认该操作确实是并行化的(为该任务创建了3个新线程).
使用英特尔的编译器提供tbb::parallel_for
了接近完全的结果.为了比较,我开始使用这个算法实现,C#
其中我也使用了parallel_for
循环,在那里我遇到了接近X4的性能提升(我选择了C++
因为这个特定任务C++
即使使用单个核心也更快).
有什么想法阻止我的代码很好地并行化?
我的代码:
template<typename T>
void static ConvertBayerToRgbImageAsIs(T* BayerChannel, T* RgbChannel, int Width, int Height, ColorSpace ColorSpace)
{
//Translates index offset in Bayer image to channel offset in RGB image
int offsets[4];
//calculate offsets according to color space
switch (ColorSpace)
{
case ColorSpace::BGGR:
offsets[0] = 2;
offsets[1] = 1;
offsets[2] = 1;
offsets[3] = 0;
break;
...other color spaces
}
memset(RgbChannel, …
Run Code Online (Sandbox Code Playgroud) 我有一个可以并行化的C++程序.我正在使用Visual Studio 2010,32位编译.
简而言之,该计划的结构如下
#define num_iterations 64 //some number
struct result
{
//some stuff
}
result best_result=initial_bad_result;
for(i=0; i<many_times; i++)
{
result *results[num_iterations];
for(j=0; j<num_iterations; j++)
{
some_computations(results+j);
}
// update best_result;
}
Run Code Online (Sandbox Code Playgroud)
由于每个some_computations()
都是独立的(读取了一些全局变量,但没有修改全局变量),我并行化了内部for
循环.
我的第一次尝试是使用boost :: thread,
thread_group group;
for(j=0; j<num_iterations; j++)
{
group.create_thread(boost::bind(&some_computation, this, result+j));
}
group.join_all();
Run Code Online (Sandbox Code Playgroud)
结果很好,但我决定尝试更多.
我试过OpenMP库
#pragma omp parallel for
for(j=0; j<num_iterations; j++)
{
some_computations(results+j);
}
Run Code Online (Sandbox Code Playgroud)
结果比boost::thread
那些更差.
然后我尝试了ppl库并使用parallel_for()
:
Concurrency::parallel_for(0,num_iterations, [=](int j) { …
Run Code Online (Sandbox Code Playgroud) 我有一个属于某个类的大项目向量.
struct item {
int class_id;
//some other data...
};
Run Code Online (Sandbox Code Playgroud)
相同的class_id可以在向量中出现多次,并且向量构造一次然后按class_id排序.因此,同一类中的所有元素在向量中彼此相邻.
我后来必须处理每个类的项目,即.我更新同一类的所有项目,但我不修改不同类的任何项目.由于我必须为所有项目执行此操作,并且代码可以简单地并行化,因此我希望将Microsoft PPL与Concurrency :: parallel_for_each()一起使用.因此,我需要一个迭代器,并提出了一个前向迭代器,它返回所有项目的范围,并以某个class_id作为代理对象.代理只是一个std :: pair,代理是迭代器的值类型.
using item_iterator = std::vector<item>::iterator;
using class_range = std::pair<item_iterator, item_iterator>;
//iterator definition
class per_class_iterator : public std::iterator<std::forward_iterator_tag, class_range> { /* ... */ };
Run Code Online (Sandbox Code Playgroud)
到现在为止,我能够循环遍历所有类并更新这样的项目.
std::vector<item> items;
//per_class_* returns a per_class_iterator
std::for_each(items.per_class_begin(), items.per_class_end(),
[](class_range r)
{
//do something for all items in r
std::for_each(r.first, r.second, /* some work */);
});
Run Code Online (Sandbox Code Playgroud)
当用Concurrency :: parallel_for_each替换std :: for_each时,代码崩溃了.调试后,我发现问题是ppl.h中第2772行的_Parallel_for_each_helper中的以下代码.
// Add a batch of work items to this functor's …
Run Code Online (Sandbox Code Playgroud) 我正在使用PPL和parallel_for语法来创建for循环.在capture子句中,我有3个变量,其中一个是类成员.由于capture子句中的变量中存在类成员,因此存在编译错误.但是,如果我在lambda体中有这个类成员,它也不会编译,并且声明的错误是封闭范围中的变量应该在capture子句中.如何进行?我应该事先将变量成员复制到局部变量,并将其传递给capture子句吗?
这是代码,使用formulaCommand类成员.
parallel_for (m_rowStart,m_rowEnd+1,[&functionEvaluation,varModel_,formulaCommand](int i)
{
MLEquationVariableModel model_(varModel_);
model_.addVariable("i", i);
model_.addVariable("j", 1);
MLEquationCommand* command_ = formulaCommand->duplicate(&model_);
double d = command_->execute().toDouble();
if(d==NO_VALUE)
{
functionEvaluation.local() = NO_VALUE;
}
else
{
functionEvaluation.local() += d;
}
delete command_;
});
Run Code Online (Sandbox Code Playgroud)
谢谢!
我正在编写一个Server应用程序,它一次从多个源获取数据并将其存储在其内部数据库中(当前为a std::set
).
我一直在关注微软的ConcRT PPL数据结构,并想知道它们的效率与使用细粒度互斥锁相比如何std::unordered_set
.例如,两个代码片段之间是否有很多性能差异:
void StdWithMutex( void )
{
std::ofstream outFile( "Test.tmp" );
std::lock_guard<std::mutex> lockGuard( m_mutex );
// Iterate through the data and write it to a file:
// m_setData is of type std::unordered_set<DataType>
for( auto data : m_setData )
{
outFile << data;
}
}
Run Code Online (Sandbox Code Playgroud)
和:
void ConcRT( void )
{
std::ofstream outFile( "Test.tmp" );
// Iterate through the data and write it to a file:
// m_setData is of type concurrency::concurrent_unordered_set
for( auto data : …
Run Code Online (Sandbox Code Playgroud) 我正在寻找将 aconcurrent_vector
从 PPL 库转换为普通 std::vector 的推荐方法。
我有一个函数,它在 a 中返回其结果,std::vector
但内部可能使用也可能不使用并行算法。目前我正在使用insert
将元素从并发向量复制到法线向量:
#ifdef PARALLEL
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in a parallel algorithm
std::vector<Foo> sv;
sv.insert(sv.begin(), cv.begin(), cv.end());
return sv;
}
#else
std::vector<Foo> Bar() {
std::vector<Foo> sv;
//Fill sv in a sequential algorithm
return sv;
}
#endif
Run Code Online (Sandbox Code Playgroud)
虽然插入操作的性能目前还不是一个真正的问题(与函数体相比),但它似乎没有必要,我想知道是否有更好的解决方案(顺便说一句:Foo
是一个不能移动的简单 POD)。
理想情况下我想要有类似的东西
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in a parallel algorithm
return static_cast<std::vector<Foo>>(cv);
}
Run Code Online (Sandbox Code Playgroud)
或者至少
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in …
Run Code Online (Sandbox Code Playgroud) 我想比较PPL和OpenMP的性能,但无法在网上找到详细的调查.我相信没有多少人对PPL有经验.
我正在使用Visual Studio 2010在Windows上开发我的软件,并且不想在短期内将其移植到其他地方.
如果可移植性不是问题,只关注性能,那么您对这两种方法有什么看法?
我们使用PPL Concurrency :: TaskScheduler将事件从我们的媒体管道分派到订阅客户端(通常是GUI应用程序).
这些事件是传递给Concurrency :: TaskScheduler :: ScheduleTask()的 C++ lambda .
但是,在负载下,管道可以以比客户端消耗它们更高的速率生成事件.
如果计划任务的"队列"大于N,我是否可以使用PPL策略使事件调度程序不对事件(实际上是计划任务)进行排队?如果没有,我将如何推出自己的?
c++ ×10
ppl ×10
c++11 ×3
concurrency ×3
openmp ×2
tbb ×2
boost-thread ×1
comparison ×1
iterator ×1
lambda ×1
parallel-for ×1
rxcpp ×1
stl ×1
threadpool ×1
visual-c++ ×1
winapi ×1