lreis2415 / SEIMS

Spatially Explicit Integrated Modeling System --- open-source, cross-platform, and high performance computation
https://lreis2415.github.io/SEIMS/
GNU General Public License v3.0
50 stars 34 forks source link

Error handling under OpenMP / 共享内存编程下的异常捕捉 #11

Open crazyzlj opened 7 years ago

crazyzlj commented 7 years ago

OpenMP内抛出异常

SEIMS中异常捕捉是一个继承于exceptionModelException类,在各个模块中,如遇到异常,只需要抛出异常,即throw ModelException(),捕获异常并打印错误信息则在主函数调用处,即invoke.cpp。 在具体模块执行计算任务时,子流域内部栅格或基于流向分层的每一层内部栅格间的计算相互独立,可以很方便的利用共享内存的方式(OpenMP)进行线程级的并行,比如,下面一段代码我们经常用到:

omp_set_num_threads(4);
#pragma omp parallel for
for (int i = 0; i < m_nCells; i++) {
    DoSomethingThatMayThrowAnException();
    if (ExceptionOccurred) {
        throw ModelException("MID", "FunctionName", "ErrorMessage!\n");
    }
}

这时候,我们期望的是:一旦计算出现异常,主程序捕获异常,打印异常信息并正常释放内存,退出程序,比如这样: 期望的捕获异常输出信息 然而,实际上(指的是在m_nCells次循环中,有大于1次异常出现),我们会得到这样: 实际上程序崩溃 此时,程序崩溃,内存没有得到完全释放,只能选择关闭程序。

什么原因呢?

Exceptions may not be thrown and caught across omp constructs. That is, if a code inside an omp for throws an exception, the exception must be caught before the end of the loop iteration; and an exception thrown inside a parallel section must be caught by the same thread before the end of the parallel section. Guide into OpenMP: Easy multithreading programming for C++ by Joel Yliluoma

换句话说,在哪个线程抛出异常,就得在哪个线程捕获,而且必须在当前代码块内捕获

如何解决呢?

Google一下关键字“C++ exception openmp loop”,我们就能发现几种解决方案,如StackoverflowBreaking Out of Loops in OpenMP,甚至还有一些论文,如Towards an Error Model for OpenMPManaging C++ OpenMP Code and Its Exception Handling等。

当然,解决思路无外乎两种:

为了减少对现有代码的修改程度,也尽量不过多暴露openmp指令代码,我们目前采用一种简单的实现方式:

omp_set_num_threads(4);
size_t errCount = 0;
#pragma omp parallel for  reduction(+:errCount)
for (int i = 0; i < m_nCells; i++) {
    DoSomethingThatMayThrowAnException();
    if (ExceptionOccurred) {
        PrintErrorMessage();
        errCount++;
    }
}
if (errCount > 0) {
    throw ModelException("MID", "FunctionName", "ErrorMessage!\n");
}

TBD

请大家在写代码的时候,注意这一点。 如有更好的解决方法,请在下面留言,我们慢慢改进!

扩展阅读

aibbgiser commented 7 years ago

It's really helpful. Cool!