OpenMP任务的正确异常处理方式及try-catch块放置规范
关于OpenMP Task中try-catch放置规则的解答
核心结论:
- 第一种用单个try-catch包裹所有task定义的写法完全无法捕获task内部抛出的异常,不符合你的需求
- 第二种在每个task内部单独定义try-catch的写法是正确的,可以满足你捕获异常、打印信息后终止程序的要求
- 不需要同时加两层try-catch,外层包裹task定义的try-catch对处理task运行时异常没有作用
为什么外层try-catch捕获不到task内部异常
OpenMP的task是异步执行的逻辑:
你在#pragma omp single块里写#pragma omp task的时候,只是向OpenMP运行时提交了一个待执行的任务,并没有立刻运行task内部的代码。task内部的逻辑会在之后由调度线程(可能是其他任意工作线程)异步执行,此时外层包裹task定义的try-catch块已经执行完成退出了,异常根本没有路径传递到外层的catch块。
另外OpenMP规范明确要求:异常不得跳出OpenMP结构化块。如果task内部抛出的异常没有在task作用域内被捕获,会直接触发程序未定义行为,通常表现为进程直接崩溃,不会向上传递到提交task的上下文。
实现说明
你的需求是只要任意task抛异常就打印信息并终止程序,直接用第二种写法即可:
每个task内部的catch块捕获到异常后,先打印你需要的错误信息,直接调用abort()即可终止整个进程,不需要额外的外层处理逻辑。
如果后续你有不终止进程、统一收集所有task异常的需求,可以自行实现线程安全的异常队列,每个task捕获异常后将异常信息推入队列,等所有task通过#pragma omp taskwait同步完成后,再在外层统一处理队列中的异常即可。
内容的提问来源于stack exchange,提问作者astrophobia
相关产品推荐
相关产品推荐

