我有以下排序的载体:
vector<unsigned> vector1;
vector<unsigned> vector2;
vector<unsigned> vector3;
...
vector<unsigned> vector30000;
我需要执行vector1与其余向量的交集。即我需要执行以下交叉点:
vectori1=intersection of vector1 with vector2;
vectori2=intersection of vector1 with vector3;
vectori3=intersection of vector1 with vector4;
...
vectori30000=intersection of vector1 with vector30000;
现在我需要找出所有非空向量的vectori1,vectori2,vectori3,...,vectori30000并将它们存储在“相交的”向量中。
为了做到这一点,我编写了以下序列化代码:
int main()
{
vector<unsigned> vector1;
vector1.push_back(10); vector1.push_back(20); vector1.push_back(30);
vector<vector<unsigned> > vecOfVectors;
vector<unsigned> vector2;
vector2.push_back(1); vector2.push_back(5); vector2.push_back(8); vector2.push_back(10);
vecOfVectors.push_back(vector2);
vector<unsigned> vector3;
vector3.push_back(3); vector3.push_back(20); vector3.push_back(25);
vecOfVectors.push_back(vector3);
vector<unsigned> vector4;
vector4.push_back(28); vector4.push_back(29); vector4.push_back(39);
vecOfVectors.push_back(vector4);
vector<vector<unsigned> > intersected;
for(vector<vector<unsigned> >::iterator it=vecOfVectors.begin(),l=vecOfVectors.end();it!=l;++it)
{
vector<unsigned> intersectedLocal;
std::set_intersection(vector1.begin(),vector1.end,(*it).begin(),(*it).end(),back_inserter(intersectedLocal));
if(!intersectedLocal.empty())
intersected.push_back(intersectedLocal);
}
}
为了提高性能,我需要并行化交集算法。我没有得到如何做同样的事情。我的尝试如下所示:
void multThreadIntersect(vector<unsigned>& vector1, vector<vector<unsigned> >::iterator it, int size,int i,vector<vector<unsigned> >& intersected,vector<int>& idIntersected)
{
if(i<size)
{
vector<unsigned> intersectedLocal;
std::set_intersection(vector1.begin(),vector1.end,(*it).begin(),(*it).end(),back_inserter(intersectedLocal));
it++;
idIntersected.push_back(i);
intersected.push_back(intersectedLocal);
auto future = std::async(std::launch::async,multThreadIntersect, vector1, it, size,intersected,idIntersected);
future.wait();
i++;
}
else
{
return;
}
}
int main()
{
vector<unsigned> vector1;
vector1.push_back(10); vector1.push_back(20); vector1.push_back(30);
vector<vector<unsigned> > vecOfVectors;
vector<unsigned> vector2;
vector2.push_back(1); vector2.push_back(5); vector2.push_back(8); vector2.push_back(10);
vecOfVectors.push_back(vector2);
vector<unsigned> vector3;
vector3.push_back(3); vector3.push_back(20); vector3.push_back(25);
vecOfVectors.push_back(vector3);
vector<unsigned> vector4;
vector4.push_back(28); vector4.push_back(29); vector4.push_back(39);
vecOfVectors.push_back(vector4);
vector<vector<unsigned> >::iterator it=vecOfVectors.begin();
int size=vecOfVectors.size();
int i=0;
vector<vector<unsigned> > intersected;
vector<int> idIntersected; //contains those i's whose intersection was non-zero
long unsigned int nThreads = std::thread::hardware_concurrency();
multThreadIntersect(vector1,it,size,i,intersected,idIntersected);
cout<<"id intersected vector:";
for(vector<int>::iterator it=idIntersected.begin(),l=idIntersected.end();it!=l;++it)
cout<<" "<<(*it);
cout<<"\n";
}
我使用的gcc版本是: gcc(GCC)4.8.2 20140120(Red Hat 4.8.2-15)
我已经在我的程序中定义了_GLIBCXX_PARALLEL。但是,由于vector1与vector2,...,vector30000的交集是相互独立的。因此,我正在考虑将vector1与vector2,vector1与vector3和vector1与vector30000并行交叉
答案 0 :(得分:2)
您可以使用OpenMP来并行它:
omp_set_num_threads(2); // here set number of threads, if not set it defaults to number of the cores in the machine
#pragma omp parallel for
for (int x = 0; x < vecOfVectors.size(); ++x)
{
vector<unsigned> intersectedLocal;
std::set_intersection(vector1.begin(), vector1.end(), vecOfVectors[x].begin(), vecOfVectors[x].end(), back_inserter(intersectedLocal));
if (!intersectedLocal.empty())
{
#pragma omp critical // execute one thread at a time
intersected.push_back(intersectedLocal);
}
}
启用OpenMP添加到链接器:-fopenmp
答案 1 :(得分:1)
有许多库/工具可以实现线程池。微软的人才,英特尔的tbb,OpenMP(根据我的经验,从易用性的降序排列)。如果有可用的话,请使用其中一个。
这是一个质量交叉函数。
它使用async
。它可以透明地转换为使用线程池,方法是将调用替换为async
,并传入线程池,或者调用由线程池支持的全局函数(取决于您使用的库):
std::vector<std::vector<unsigned>>
mass_intersect(
std::vector<unsigned> filter,
std::initializer_list< std::reference_wrapper<std::vector<unsigned> const> > targets
) {
std::vector< std::future< std::vector<unsigned>>> working;
working.reserve(targets.size());
for (auto const& rhs:targets) {
working.push_back( std::async( std::launch::async, [&rhs,&filter]{
std::vector<unsigned> result;
// do filter on rhs.get() and filter into result
return result;
});
}
// convert the above futures into a return value:
std::vector< std::vector<unsigned>> retval;
retval.reserve(working.size());
for (auto&& r_f:working) {
auto r = r_f.get(); // block
if (r.empty()) continue;
retval.push_back(std::move(r));
}
return retval;
}
我离开了实际的交叉点代码未完成。
它将vector
s作为const向量的引用包。您可以使用以下方法构建它:
{ std::ref( v1 ), std::ref( v2 ), std::ref(v3) }
但实际上,它所需要的只是一个可迭代的源向量集合。
这是一个质量交叉函数
它使用async
。它可以透明地转换为使用线程池,方法是将调用替换为async
,并将线程池传递给:
std::vector<std::vector<unsigned>>
mass_intersect(
std::vector<unsigned> filter,
std::initializer_list< std::reference_wrapper<std::vector<unsigned> const> > targets
) {
std::vector< std::future< std::vector<unsigned>>> working;
working.reserve(targets.size());
for (auto const& rhs:targets) {
working.push_back( std::async( std::launch::async, [&rhs,&filter]{
std::vector<unsigned> result;
// do filter on rhs.get() and filter into result
return result;
});
}
// convert the above futures into a return value:
std::vector< std::vector<unsigned>> retval;
retval.reserve(working.size());
for (auto&& r_f:working) {
auto r = r_f.get(); // block
if (r.empty()) continue;
retval.push_back(std::move(r));
}
return retval;
}
我离开了实际的交叉点代码未完成。
它将vector
s作为const向量的引用包。您可以使用以下方法构建它:
{ std::ref( v1 ), std::ref( v2 ), std::ref(v3) }
但实际上,它所需要的只是一个可迭代的源向量集合。
现在,大多数现有线程池不会与std::future
和C ++ 11同步原语无关地进行交互(除了其他原因,因为它们先于它)。因此,除非您编写自己的线程池,否则必须进行一些调整。
如果你想编写一个线程池,这里有一个简短的草图一个线程池可以写一个条件变量,mutex
(或shared_timed_mutex
)和一个{{1的向量}}第
它维护一组线程,从promised_task
队列中弹出任务。
添加任务时,界面看起来很像promised_task
。界面草图:
async
我最近在另一个堆栈溢出答案中写了sketch of an implementation。以上只支持一次添加工作线程1:上面的界面允许您一次添加任意数量的线程。改变这很容易。它也只支持struct thread_pool {
template<class F>
std::future<std::result_of_t<std::decay_t<F>()>> queue(F&&f);
std::future<void> abort(); // empties queue, kills all threads
size_t thread_count() const;
void add_threads(size_t n=1);
~thread_pool();
thread_pool();
thread_pool(thread_pool&&)=delete;
thread_pool& operator=(thread_pool&&)=delete;
private:
// stuff
};
返回类型 - 再次,应该很容易修复。