我有一个代码可以在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 ++快?
答案 0 :(得分:1)
改进两个版本的明显方法是使用顺序数组访问。您的循环变量是(外部到内部)d,i,j
,但是循环索引是[d + w3*j + w3*w2*i]
。要顺序访问数组,[0]
后应跟[1]
,这意味着d
应该是内部循环变量,而不是外部循环变量。