c++ 在派生函数中启动 OMP 线程
c++ Start an OMP thread in a derived function
假设我有一个基类,其中包含一个带有两个OMP线程的虚函数:
class Parent {
public:
Parent() {}
~Parent() {}
virtual void f() {
#pragma omp parallel sections
{
#pragma omp section
{
// do_something_1();
}
#pragma omp section
{
// do_something_2();
}
}
}
}
然后我有一个这样的派生类:
class Child : public Parent {
public:
Child() {}
~Child() {}
void f() {
Parent::f();
// Other thread OMD
}
}
我想最后让来自父类的两个线程和来自 Child 的线程运行,但它不起作用。这种设计甚至可能吗?
问题是 OpenMP 指令位于父级的虚拟函数内,因此 在派生类中不可见。在派生类中调用父代码时 这提出了两种可能的解决方案,都有优点和缺点。
版本 1 将父级的操作保密,但只能额外扩展一次 水平。
class Parent {
public:
void f() {
#pragma omp parallel sections
{
#pragma omp section
{
// do_something_1();
}
#pragma omp section
{
// do_something_2();
}
#pragma omp section
{
this->f_impl();
}
}
}
private:
virtual void f_impl() {}; // do nothing placeholder
}
class Child : public Parent {
private:
void f_impl() override;
}
或
版本 2 可以无限期扩展,但需要公开每个父级的内部结构。
class Parent {
public:
virtual void f() {
#pragma omp parallel sections
{
#pragma omp section
{
f_impl1();
}
#pragma omp section
{
f_impl2();
}
}
}
protected:
void f_impl1();
void f_impl2();
}
class Child : public Parent {
public:
virtual void f() {
#pragma omp parallel sections
{
#pragma omp section
{
f_impl1();
}
#pragma omp section
{
f_impl2();
}
#pragma omp section
{
f_impl3();
}
}
}
protected:
void f_impl3();
}
class Child2 : public Child {
public:
virtual void f() {
#pragma omp parallel sections
{
#pragma omp section
{
f_impl1();
}
#pragma omp section
{
f_impl2();
}
#pragma omp section
{
f_impl3();
}
#pragma omp section
{
f_impl4();
}
}
}
protected:
void f_impl4();
}
在这种情况下,我宁愿建议使用任务,并确保所有内容都在并行上下文中执行,例如:
// prepare the parallel context somewhere outside
#pragma omp parallel
#pargma omp single
run();
class Parent {
public:
Parent() {}
~Parent() {}
virtual void f() {
#pragma omp task
{
// do_something_1();
}
// do_something_2();
#pragma omp taskwait
// It's not nice for reasoning about code to keep tasks running here
}
}
class Child : public Parent {
public:
Child() {}
~Child() {}
void f() {
// swap the order in the code
// to account for taskwait at the end of paraent::f
#pragma omp task
{
// Other thread OMD
}
Parent::f();
// if you feel like it, you can also add a taskwait here
}
}
如您所见,如果在应用程序中确保并行上下文(但使用代码的单一执行),则可以轻松地使用任务来实现派生调用之间的并行化。但是,请注意在函数调用结束时保留执行任务,因为这可能很危险。确保调用方知道何时必须taskwait
以确保操作完成 - 或者交换它,以便调用方并行执行任务与被调用方执行的任何操作。
如果没有线程团队,也可以按需创建并行上下文,但我认为这不那么干净且更危险。
相关文章:
- 如何创建一个空的全局类并在启动时实例化它
- 即使我读取了所有内容,在FIFO上打开的QSocketNotifier也会一直启动
- C++omp没有显著改善
- 使用 std::string () const 函数启动线程或未来
- 如何修复valgrind启动时的致命错误(与libc6-dbg和libc6-dbg:i386连接)
- 等待整个 omp 块完成,然后再调用第二个函数
- 将向量作为类>(值)<向量启动和向量<类>[值]有什么区别
- 如何创建线程序列以按照启动顺序执行任务?
- WINAPI 注册应用程序重新启动时不清除打开的套接字
- 在挂钩启动新线程时解除挂钩进程
- 程序无法启动,因为缺少 libmpc-3.dll
- 从 exe 文件 (Visual Studio ) 启动时调试断言失败
- QSerialPort 在应用程序启动之前正在使用中
- 无法在 Arch Linux 中启动虚幻引擎 4
- C++关于指针和使用函数将它们启动到堆的行为究竟是什么?
- 如何使用 ctypes 停止和重新启动从 Python 运行的C++代码
- 程序在使用 system() 启动另一个可执行文件时停止
- Qt 和 Android - 如何使用 Qandroidjniobject 启动相机
- OMP 不启动线程
- c++ 在派生函数中启动 OMP 线程