Android OpenCV并行循环

Android OpenCV parallelize loops

本文关键字:循环 并行 OpenCV Android      更新时间:2023-10-16

我知道OpenMP包含在NDK中(这里的用法示例:http://recursify.com/blog/2013/08/09/openmp-on-android)。我已经按照页面上的说明做了,但当我在扫描向量的简单for循环中使用:#pragma omp for时,该应用程序会崩溃,并发出著名的"致命信号11"。

我在这里错过了什么?顺便说一句,我使用了一个来自Android示例的修改示例,它是教程2混合处理。我只想在使用OpenCV时,将jni c++文件中的一些for循环和嵌套for循环并行化(多线程)。

感谢您的帮助/建议!

编辑:添加示例代码:

#pragma omp parallel for
Mat tmp(iheight, iwidth, CV_8UC1);
for (int x = 0; x < iheight; x++) {
    for (int y = 0; y < iwidth; y++) {
        int value = (int) buffer[x * iwidth + y];
        tmp.at<uchar>(x, y) = value;
    }
}

基于此:http://www.slideshare.net/noritsuna/how-to-use-openmp-on-native-activity谢谢

我认为这是GOMP中已知的问题,请参阅Bug 42616和Bug 52738。
这是关于如果你试图在非主线程上使用OpenMP指令或函数,你的应用程序将崩溃,并且可以追溯到gomp_thread()函数(请参见libgomp/libgomp.h@line 362和368),它为你创建的线程返回NULL

#ifdef HAVE_TLS
    extern __thread struct gomp_thread gomp_tls_data;
    static inline struct gomp_thread *gomp_thread (void)
    {
      return &gomp_tls_data;
    }
#else
    extern pthread_key_t gomp_tls_key;
    static inline struct gomp_thread *gomp_thread (void)
    {
      return pthread_getspecific (gomp_tls_key);
    }
#endif

正如您所看到的,GOMP根据线程本地存储(TLS)是否可用而使用不同的实现。

  • 如果可用,则设置HAVE_TLS标志,并使用全局变量来跟踪每个线程的状态
  • 否则,线程本地数据将通过函数pthread_setspecific进行管理

在早期版本的NDK中,不支持线程本地存储(__thread关键字),因此不会定义HAVE_TLS,因此将使用pthread_setspecific
备注:我不确定上一版本的NDK是否支持__thread,但在这里你可以阅读关于Android TLS的相同答案

GOMP创建工作线程时,会在函数gomp_thread_start()(第72行)中设置线程特定数据:

#ifdef HAVE_TLS
    thr = &gomp_tls_data;
#else
    struct gomp_thread local_thr;
    thr = &local_thr;
    pthread_setspecific (gomp_tls_key, thr);
#endif

但是,当应用程序独立创建线程时,不会设置线程特定的数据,因此gomp_thread()函数返回NULL。这会导致崩溃,当支持TLS时这不是问题,因为使用的全局变量将始终可用

我记得这个问题已经修复了android-ndk-r10d,但它只适用于后台进程(没有Java)。这意味着,当你启用OpenMP并从JNI(Java Android中的名称)创建一个本地线程时,你的应用程序将崩溃。