JNI原生函数为何始终返回0耗时?Android开发技术求助
问题原因
你的代码返回0是因为编译器死代码消除优化:由于arr1和matrix1在创建后没有被任何实际操作使用(除了创建),编译器会判定这些代码是“无用的”,直接跳过执行,导致begin和end的时间差几乎为0,最终返回0。而当你加入matrix1(1,1)时,编译器认为这个对象被使用了,才会执行创建数组和矩阵的代码。
解决方案
无需修改返回值,只需让编译器认为arr1和matrix1是被使用的,以下是几种可行方法:
方法1:强制读取变量/对象(推荐)
在创建matrix1后,添加一行强制读取对象的代码,编译器就不会优化掉相关创建逻辑:
JNIEXPORT jint JNICALL Java_com_app_Native_test(JNIEnv *env, jobject object) { steady_clock::time_point begin = steady_clock::now(); int lenght = 500000000; int * arr1 = new int[lenght]; for(int i = 0; i < lenght; i++) { *(arr1+i) = i+1; } matrix<int, 100> matrix1(arr1, lenght); // 强制读取matrix1,阻止编译器优化 (void)matrix1(1, 1); steady_clock::time_point end = steady_clock::now(); return duration_cast<microseconds>(end-begin).count(); }
(void)是告诉编译器我们故意忽略返回值,避免未使用变量的警告。
方法2:使用空函数“消耗”变量
定义一个空函数,将arr1和matrix1作为参数传入,编译器会认为这些变量被使用:
// 定义在函数外或者头文件中 void preventOptimization(const void*) {} JNIEXPORT jint JNICALL Java_com_app_Native_test(JNIEnv *env, jobject object) { steady_clock::time_point begin = steady_clock::now(); int lenght = 500000000; int * arr1 = new int[lenght]; for(int i = 0; i < lenght; i++) { *(arr1+i) = i+1; } matrix<int, 100> matrix1(arr1, lenght); // 传入变量,阻止优化 preventOptimization(arr1); preventOptimization(&matrix1); steady_clock::time_point end = steady_clock::now(); return duration_cast<microseconds>(end-begin).count(); }
注意不要把这个空函数定义成内联函数,否则编译器可能还是会优化掉。
方法3:局部禁用编译器优化
如果上面的方法无效,可以用编译器指令临时关闭当前代码块的优化(以GCC/Clang为例):
JNIEXPORT jint JNICALL Java_com_app_Native_test(JNIEnv *env, jobject object) { steady_clock::time_point begin = steady_clock::now(); // 临时关闭优化 #pragma GCC push_options #pragma GCC optimize ("O0") int lenght = 500000000; int * arr1 = new int[lenght]; for(int i = 0; i < lenght; i++) { *(arr1+i) = i+1; } matrix<int, 100> matrix1(arr1, lenght); // 恢复之前的优化级别 #pragma GCC pop_options steady_clock::time_point end = steady_clock::now(); return duration_cast<microseconds>(end-begin).count(); }
这种方法会影响代码块的执行效率,仅在其他方法无效时使用。
内容的提问来源于stack exchange,提问作者NEKKITIS
相关产品推荐
相关产品推荐

