Jni本机C ++并没有比Android中的Java快

时间:2018-08-08 09:42:18

标签: java android c++

我有一个代码可以在Java中处理大型float数组,但是它太慢了。因此,我尝试使用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 ++快?

1 个答案:

答案 0 :(得分:1)

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