gpt4 book ai didi

android - NDK性能

转载 作者:行者123 更新时间:2023-11-29 00:25:27 28 4
gpt4 key购买 nike

我刚刚开始使用 NDK 来探索我所 promise 的性能提升。为了感受差异,我尝试了一个愚蠢的数字运算任务(将 Mandelbrot 集渲染为位图)并将其与相同代码的 Java 版本进行比较。令我大吃一惊的是,C 版本要慢得多(平均 5.0 秒,而我的 HTC One 为 1.6 秒)。更奇怪的是,成本不是因为进行 native 调用的开销,而是实际的数字运算需要更长的时间。

这不可能吧?我错过了什么?

C 版本(删除了调试计时器代码):

const int MAX_ITER = 63;
const float MAX_DEPTH = 16;

static uint16_t rgb565(int red, int green, int blue)
{
return (uint16_t)(((red << 8) & 0xf800) | ((green << 2) & 0x03e0) | ((blue >> 3) & 0x001f));
}

float zAbs(float re, float im) {
return re*re + im*im;
}

int depth(float cRe, float cIm) {
int i=0;
float re, im;
float zRe = 0.0f;
float zIm = 0.0f;
while ((zAbs(zRe, zIm) < MAX_DEPTH) && (i < MAX_ITER)) {
re = zRe * zRe - zIm * zIm + cRe;
im = 2.0f * zRe * zIm + cIm;
zRe = re;
zIm = im;
i++;
}
return i;
}

extern "C"
void Java_com_example_ndktest_MainActivity_renderFractal(JNIEnv* env, jobject thiz, jobject bitmap, float re0, float im0, float b)
{
AndroidBitmapInfo info;
void* pixels;
int ret;

long t0 = currentTimeInMilliseconds();

if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
}

if (info.format != ANDROID_BITMAP_FORMAT_RGB_565) {
LOGE("Bitmap format is not RGB_565 !");
return;
}

if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
}


int w = info.width;
int h = info.height;

float re, im;
int z = 0;
uint16_t* px = (uint16_t*)pixels;
for(int y=0; y<h; y++) {
im = im0 + b*((float)y/(float)h);
for(int x=0; x<info.width; x++) {
re = re0 + b*((float)x/(float)w);
z = depth(re, im);
px[y*w + x] = rgb565(0, z*4, z * 16);
}
}

AndroidBitmap_unlockPixels(env, bitmap);
}

Java 版本:

    private static final int MAX_ITER = 63;
private static final float MAX_DEPTH = 16;

static int rgb565(int red, int green, int blue)
{
return ((red << 8) & 0xf800) | ((green << 2) & 0x03e0) | ((blue >> 3) & 0x001f);
}

static float zAbs(float re, float im) {
return re*re + im*im;
}

static int depth(float cRe, float cIm) {
int i=0;
float re, im;
float zRe = 0.0f;
float zIm = 0.0f;
while ((zAbs(zRe, zIm) < MAX_DEPTH) && (i < MAX_ITER)) {
re = zRe * zRe - zIm * zIm + cRe;
im = 2.0f * zRe * zIm + cIm;
zRe = re;
zIm = im;
i++;
}
return i;
}

static void renderFractal(Bitmap bitmap, float re0, float im0, float b)
{
int w = bitmap.getWidth();
int h = bitmap.getHeight();

int[] pixels = new int[w * h];

bitmap.getPixels(pixels, 0, w, 0, 0, w, h);

float re, im;
int z = 0;
for(int y=0; y<h; y++) {
im = im0 + b*((float)y/(float)h);
for(int x=0; x<w; x++) {
re = re0 + b*((float)x/(float)w);
z = depth(re, im);
pixels[y*w + x] = rgb565(0, z*4, z * 16);
}
}

bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
}

最佳答案

如评论中所述,这是因为 NDK 代码是为 armeabi 目标而不是 armeabi-v7a 目标构建的。前者旨在适用于广泛的硬件,包括没有浮点硬件的设备,因此它在软件中进行所有浮点计算。

为 armeabi-v7a 构建启用了 VFP 指令,因此任何严重依赖浮点计算的东西都会显着加速。

如果您专门为 armeabi-v7a 构建,您将排除相当广泛的设备选择,甚至是相对较新的设备(例如三星 Galaxy Ace)。这些设备支持 VFP,但 CPU 基于 ARMv6 指令集而不是 ARMv7。没有“带有 VFP 的 ARMv7 之前的 CPU”构建目标,因此您必须为 armeabi 构建,或者使用自定义构建规则并仔细选择支持的设备。

另一方面,您可以通过在 armeabi-v7a 库中指定硬浮点 ABI(-mhard-float -- 需要 NDK r9b)来获得小幅性能提升。

FWIW,像 Dalvik 中的编译器这样的即时编译器的卖点之一是它们可以识别系统功能并适本地调整代码生成。

关于android - NDK性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19981969/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com