首页 > 解决方案 > Jni native C++在android中并不比java快

问题描述

我有一个在java中处理大浮点数组的代码,但它太慢了。所以我尝试使用Jni原生C++来提高性能和处理速度,可惜还是太慢了。甚至比java版本慢。这是我的部分代码,您可以告诉我如何改进它。

在android java中:

private float[] nonMaxSuppression_java( float[] map,int w1,int w2,int w3, int window) {
    int size  = w1*w2*w3;
    float[] original = new float[w1*w2*w3];
    for(int d =0; d<w3;d++) {
        for (int i = 0; i < w1; i++) {
            for (int j = 0; j <w2; j++) {
                float max = -99;
                float current = map[d+w3*(j+w2*i)];
                for (int row_offset = 0; row_offset < window; row_offset++) {
                    for (int col_offset = 0; col_offset < window; col_offset++) {
                        int row_index = i + row_offset - window / 2;
                        int col_index = j + col_offset - window / 2;
                        if (row_index < w1 && col_index < w2 && row_index >= 0 && col_index >= 0) {
                            float a = map[d+w3*(col_index+w2*row_index)];
                            if(map[d+w3*(col_index+w2*row_index)] > max) {
                                max = map[d+w3*(col_index+w2*row_index)];
                            }
                        }
                    }
                }
                if (current != max) {
                    original[d + w3 * (j + w2 * i)] = 0;
                } else {
                    original[d + w3 * (j + w2 * i)] = map[d+w3*(j+w2*i)];
                }
            }
        }
    }
    return original;
}

在本机 C++ 中:

extern "C"
JNIEXPORT jfloatArray JNICALL
Java_com_asus_poseestimator_JNIUtils_nonMaxSuppression(JNIEnv *env, jobject instance, jfloatArray map_,jint w1,jint w2,jint w3, jint window) {
jfloat *map = env->GetFloatArrayElements(map_, 0);
int size  = w1*w2*w3
;
jfloatArray result = env->NewFloatArray(size);
float *original = new float[w1*w2*w3];
for(int d =0; d<w3;d++) {
    for (int i = 0; i < w1; i++) {
        for (int j = 0; j <w2; j++) {
            float max = -99;
            float current = MAP(i,j,d);
            for (int row_offset = 0; row_offset < window; row_offset++) {
                for (int col_offset = 0; col_offset < window; col_offset++) {
                    int row_index = i + row_offset - window / 2;
                    int col_index = j + col_offset - window / 2;
                    if (row_index < w1 && col_index < w2 && row_index >= 0 && col_index >= 0) {
                        if(MAP(row_index,col_index,d) > max) {
                            max = MAP(row_index, col_index, d);
                        }
                    }
                }
            }
            if (current != max) {
                original[d + w3 * (j + w2 * i)] = 0;
            } else {
                original[d + w3 * (j + w2 * i)] = MAP(i, j, d);
            }
        }
    }
}
env->SetFloatArrayRegion(result, 0, size, original);
env->ReleaseFloatArrayElements(map_,map,0);
delete [] original;
return result;

}

我使用 Cmake 构建 JNI

   cmake {
        // for neon optimization:
        abiFilters "armeabi-v7a"
        cppFlags "-DCMAKE_BUILD_TYPE:STRING=Release -DHAVE_NEON -O3 -Wno-parentheses -mfpu=neon -mfloat-abi=softfp -march=armv7-a"
    }

为什么 java 运行这个函数比原生 C++ 更快?

标签: javaandroidc++

解决方案


改进这两个版本的明显方法是使用顺序数组访问。您的循环变量是(从外到内)d,i,j,但您的循环索引是[d + w3*j + w3*w2*i]. 要按顺序访问数组,[0]后面应该跟[1]which 表示d应该是内部循环变量,而不是外部循环变量。


推荐阅读