Examples of NEON in Android and neonandroid

Source: Internet
Author: User
Tags time in milliseconds

Examples of NEON in Android and neonandroid

1. Open Eclipse, File --> New --> AndroidApplication Project --> Application Name: Hello-Neon, Project Name: Hello-Neon, Package Name: com. hello_neon.android, Minimum Required SDK: API 9: Android 2.3 (Gingerbread), Next --> remove the check box for Create custom launcher icon, Next --> ActivityName: Hello_NeonProjectActivity, Finish.

2. Open src --> com. hello_neon.android --> Hello_NeonProjectActivity.java under the Hello-Neon project and change its content:

package com.hello_neon.android;import android.os.Bundle;import android.app.Activity;import android.widget.TextView;public class Hello_NeonProjectActivity extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        /* Create a TextView and set its content.         * the text is retrieved by calling a native function.         */        TextView  tv = new TextView(this);        tv.setText( stringFromJNI() );        setContentView(tv);    }    /* A native method that is implemented by the     * 'helloneon' native library, which is packaged with this application.     */    public native String  stringFromJNI();    /* this is used to load the 'helloneon' library on application     * startup. The library has already been unpacked into     * /data/data/com.example.neon/lib/libhelloneon.so at     * installation time by the package manager.     */    static {        System.loadLibrary("helloneon");    }}

3. Save the Hello_NeonProjectActivity.java file, open the command line window, locate it in the \ bin \ classes directory, and enter the command javah-classpath D: \ ProgramFiles \ Android \ android-sdk \ platforms \ android-9 \ android. jar; com. hello_neon.android.Hello_NeonProjectActivity will generate the com_hello_neon_android_Hello_NeonProjectActivity.h file under the \ bin \ classes directory (Description :*. jar can also be another version );

4. Select the Hello-Neon project and right-click --> New --> Folder to create a jni Folder. in this Folder, add Android. mk, Application. mk, helloneon. c, helloneon-intrinsics.c, helloneon-intrinsics.h five files, the content is:

Android. mk:

LOCAL_PATH: = $ (call my-dir) include $ (CLEAR_VARS) LOCAL_MODULE: = helloneon # Fill in the source file path LOCAL_SRC_FILES: = helloneon. c helloneon-intrinsics.c # default include header file path LOCAL_C_INCLUDES: =\$ (LOCAL_PATH) \ $ (LOCAL_PATH )/.. # A series of projects after-g are added to use the arm_neon-h header file,-mfloat-abi = softfp-mfpu = neon using arm_neon.h must be LOCAL_CFLAGS: =-g-mfloat-abi = softfp-mfpu = neon-march = armv7-a-mtune = cortex-a8LOCAL_LDLIBS: =-lz-llogTARGET_ARCH_ABI: = armeabi-v7a LOCAL_ARM_MODE: = armifeq ($ (TARGET_ARCH_ABI ), armeabi-v7a) # Use NEON optimization technology LOCAL_ARM_NEON: = true # LOCAL_CFLAGS: =-DHAVE_NEON = nodes: = cpufeatures # generate dynamic call Library include $ (BUILD_SHARED_LIBRARY) $ (call import-module, cpufeatures)

Application. mk:

APP_PROJECT_PATH: = $ (call my-dir )/.. APP_PLATFORM: = android-10 # choose which library to compile against in your MakefileAPP_STL: = stlport_static # APP_ABI specifies the type of the compiled target platform and can be optimized for different platforms, x86 or armeabi-v7a # Build both ARMv5TE and ARMv7-A machine code. APP_ABI: = armeabi armeabi-v7aAPP_CPPFLAGS + =-fexceptions # for using c ++ features, you need to enable these in your MakefileAPP_CPP_FEATURES + = exceptions rtti

Helloneon. c:

#include <jni.h>#include <time.h>#include <stdio.h>#include <stdlib.h>#include <cpu-features.h>#include "helloneon-intrinsics.h"#define DEBUG 0#define HAVE_NEON#if DEBUG#include <android/log.h>#  define  D(x...)  __android_log_print(ANDROID_LOG_INFO,"helloneon",x)#else#  define  D(...)  do {} while (0)#endif/* return current time in milliseconds */static doublenow_ms(void){    struct timespec res;    clock_gettime(CLOCK_REALTIME, &res);    return 1000.0*res.tv_sec + (double)res.tv_nsec/1e6;}/* this is a FIR filter implemented in C */static voidfir_filter_c(short *output, const short* input, const short* kernel, int width, int kernelSize){    int  offset = -kernelSize/2;    int  nn;    for (nn = 0; nn < width; nn++) {        int sum = 0;        int mm;        for (mm = 0; mm < kernelSize; mm++) {            sum += kernel[mm]*input[nn+offset+mm];        }        output[nn] = (short)((sum + 0x8000) >> 16);    }}#define  FIR_KERNEL_SIZE   32#define  FIR_OUTPUT_SIZE   2560#define  FIR_INPUT_SIZE    (FIR_OUTPUT_SIZE + FIR_KERNEL_SIZE)#define  FIR_ITERATIONS    600static const short  fir_kernel[FIR_KERNEL_SIZE] = {    0x10, 0x20, 0x40, 0x70, 0x8c, 0xa2, 0xce, 0xf0, 0xe9, 0xce, 0xa2, 0x8c, 070, 0x40, 0x20, 0x10,    0x10, 0x20, 0x40, 0x70, 0x8c, 0xa2, 0xce, 0xf0, 0xe9, 0xce, 0xa2, 0x8c, 070, 0x40, 0x20, 0x10 };static short        fir_output[FIR_OUTPUT_SIZE];static short        fir_input_0[FIR_INPUT_SIZE];static const short* fir_input = fir_input_0 + (FIR_KERNEL_SIZE/2);static short        fir_output_expected[FIR_OUTPUT_SIZE];/* This is a trivial JNI example where we use a native method * to return a new VM String. See the corresponding Java source * file located at: * *   apps/samples/hello-neon/project/src/com/example/neon/HelloNeon.java */JNIEXPORT jstring JNICALL Java_com_hello_1neon_android_Hello_1NeonProjectActivity_stringFromJNI(JNIEnv *env, jobject thiz){    char*  str;    uint64_t features;    char buffer[512];    char tryNeon = 0;    double  t0, t1, time_c, time_neon;    /* setup FIR input - whatever */    {        int  nn;        for (nn = 0; nn < FIR_INPUT_SIZE; nn++) {            fir_input_0[nn] = (5*nn) & 255;        }        fir_filter_c(fir_output_expected, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);    }    /* Benchmark small FIR filter loop - C version */    t0 = now_ms();    {        int  count = FIR_ITERATIONS;        for (; count > 0; count--) {            fir_filter_c(fir_output, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);        }    }    t1 = now_ms();    time_c = t1 - t0;    asprintf(&str, "FIR Filter benchmark:\nC version          : %g ms\n", time_c);    strlcpy(buffer, str, sizeof buffer);    free(str);    strlcat(buffer, "Neon version   : ", sizeof buffer);    if (android_getCpuFamily() != ANDROID_CPU_FAMILY_ARM) {        strlcat(buffer, "Not an ARM CPU !\n", sizeof buffer);        goto EXIT;    }    features = android_getCpuFeatures();    if ((features & ANDROID_CPU_ARM_FEATURE_ARMv7) == 0) {        strlcat(buffer, "Not an ARMv7 CPU !\n", sizeof buffer);        goto EXIT;    }    /* HAVE_NEON is defined in Android.mk ! */#ifdef HAVE_NEON    if ((features & ANDROID_CPU_ARM_FEATURE_NEON) == 0) {        strlcat(buffer, "CPU doesn't support NEON !\n", sizeof buffer);        goto EXIT;    }    /* Benchmark small FIR filter loop - Neon version */    t0 = now_ms();    {        int  count = FIR_ITERATIONS;        for (; count > 0; count--) {            fir_filter_neon_intrinsics(fir_output, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);        }    }    t1 = now_ms();    time_neon = t1 - t0;    asprintf(&str, "%g ms (x%g faster)\n", time_neon, time_c / (time_neon < 1e-6 ? 1. : time_neon));    strlcat(buffer, str, sizeof buffer);    free(str);    /* check the result, just in case */    {        int  nn, fails = 0;        for (nn = 0; nn < FIR_OUTPUT_SIZE; nn++) {            if (fir_output[nn] != fir_output_expected[nn]) {                if (++fails < 16)                    D("neon[%d] = %d expected %d", nn, fir_output[nn], fir_output_expected[nn]);            }        }        D("%d fails\n", fails);    }#else /* !HAVE_NEON */    strlcat(buffer, "Program not compiled with ARMv7 support !\n", sizeof buffer);#endif /* !HAVE_NEON */EXIT:    return (*env)->NewStringUTF(env, buffer);}

Helloneon-intrinsics.h:

#ifndef HELLONEON_INTRINSICS_H#define HELLONEON_INTRINSICS_Hvoid fir_filter_neon_intrinsics(short *output, const short* input, const short* kernel, int width, int kernelSize);#endif /* HELLONEON_INTRINSICS_H */

Helloneon-intrinsics.c:

#include "helloneon-intrinsics.h"#include <arm_neon.h>/* this source file should only be compiled by Android.mk when targeting * the armeabi-v7a ABI, and should be built in NEON mode */voidfir_filter_neon_intrinsics(short *output, const short* input, const short* kernel, int width, int kernelSize){#if 1   int nn, offset = -kernelSize/2;   for (nn = 0; nn < width; nn++)   {        int mm, sum = 0;        int32x4_t sum_vec = vdupq_n_s32(0);        for(mm = 0; mm < kernelSize/4; mm++)        {            int16x4_t  kernel_vec = vld1_s16(kernel + mm*4);            int16x4_t  input_vec = vld1_s16(input + (nn+offset+mm*4));            sum_vec = vmlal_s16(sum_vec, kernel_vec, input_vec);        }        sum += vgetq_lane_s32(sum_vec, 0);        sum += vgetq_lane_s32(sum_vec, 1);        sum += vgetq_lane_s32(sum_vec, 2);        sum += vgetq_lane_s32(sum_vec, 3);        if(kernelSize & 3)        {            for(mm = kernelSize - (kernelSize & 3); mm < kernelSize; mm++)                sum += kernel[mm] * input[nn+offset+mm];        }        output[nn] = (short)((sum + 0x8000) >> 16);    }#else /* for comparison purposes only */    int nn, offset = -kernelSize/2;    for (nn = 0; nn < width; nn++) {        int sum = 0;        int mm;        for (mm = 0; mm < kernelSize; mm++) {            sum += kernel[mm]*input[nn+offset+mm];        }        output[nn] = (short)((sum + 0x8000) >> 16);    }#endif}

5. Use NDK to generate. so file: select project --> Properties --> Builders --> New --> Select Program --> OK, Name: Hello_Neon_Builder, Location: D: \ ProgramFiles \ Android \ android-sdk \ android-ndk-r9 \ ndk-build.cmd, Working Directory: E: \ NEON \ Eclipse \ Hello-Neon --> Apply, select Refresh, check Refreshresources upon completion, select Specific resources and click Specify Resources ..., Check the libs folder under the Hello-Neon project, Finish --> Apply, BuildOptions, and Allocate Console (necessary for input), After a "Clean", During manualbuilds, During auto builds, specify working set of relevant resources, click SpecifyResoures ..., Check the jni folder under the Hello-Neon project and Finish --> Apply --> OK. The libhelloneon. so file is generated in the libs folder;

6. Select Hello-Neon, --> Run As --> AndroidApplication. The running result is:

FIRFilter benchmark:

C version: 282.84 MS

Neon version: 135985 MS (x2.07994 faster)

The above is the operation procedure of the. c file. If the. c file is a. cpp file, you need to change the two files:

1. Change Android. mk:

LOCAL_PATH: = $ (call my-dir) include $ (CLEAR_VARS) LOCAL_MODULE: = helloneon # Fill in the source file path LOCAL_SRC_FILES: = helloneon. cpp helloneon-intrinsics.cpp # default include header file path LOCAL_C_INCLUDES: =\$ (LOCAL_PATH) \ $ (LOCAL_PATH )/.. # A series of projects after-g are added to use the arm_neon-h header file,-mfloat-abi = softfp-mfpu = neon using arm_neon.h must be LOCAL_CFLAGS: =-g-mfloat-abi = softfp-mfpu = neon-march = armv7-a-mtune = cortex-a8LOCAL_LDLIBS: =-lz-llogTARGET_ARCH_ABI: = armeabi-v7a LOCAL_ARM_MODE: = armifeq ($ (TARGET_ARCH_ABI ), armeabi-v7a) # Use NEON optimization technology LOCAL_ARM_NEON: = true # LOCAL_CFLAGS: =-DHAVE_NEON = nodes: = cpufeatures # generate dynamic call Library include $ (BUILD_SHARED_LIBRARY) $ (call import-module, cpufeatures)

2. Change helloneon. c:

#include <jni.h>#include <time.h>#include <stdio.h>#include <stdlib.h>#include <cpu-features.h>#include "helloneon-intrinsics.h"#define DEBUG 0#define HAVE_NEON#ifdef __cplusplusextern "C" {#endif#if DEBUG#include <android/log.h>#  define  D(x...)  __android_log_print(ANDROID_LOG_INFO,"helloneon",x)#else#  define  D(...)  do {} while (0)#endif/* return current time in milliseconds */static doublenow_ms(void){    struct timespec res;    clock_gettime(CLOCK_REALTIME, &res);    return 1000.0*res.tv_sec + (double)res.tv_nsec/1e6;}/* this is a FIR filter implemented in C */static voidfir_filter_c(short *output, const short* input, const short* kernel, int width, int kernelSize){    int  offset = -kernelSize/2;    int  nn;    for (nn = 0; nn < width; nn++) {        int sum = 0;        int mm;        for (mm = 0; mm < kernelSize; mm++) {            sum += kernel[mm]*input[nn+offset+mm];        }        output[nn] = (short)((sum + 0x8000) >> 16);    }}#define  FIR_KERNEL_SIZE   32#define  FIR_OUTPUT_SIZE   2560#define  FIR_INPUT_SIZE    (FIR_OUTPUT_SIZE + FIR_KERNEL_SIZE)#define  FIR_ITERATIONS    600static const short  fir_kernel[FIR_KERNEL_SIZE] = {    0x10, 0x20, 0x40, 0x70, 0x8c, 0xa2, 0xce, 0xf0, 0xe9, 0xce, 0xa2, 0x8c, 070, 0x40, 0x20, 0x10,    0x10, 0x20, 0x40, 0x70, 0x8c, 0xa2, 0xce, 0xf0, 0xe9, 0xce, 0xa2, 0x8c, 070, 0x40, 0x20, 0x10 };static short        fir_output[FIR_OUTPUT_SIZE];static short        fir_input_0[FIR_INPUT_SIZE];static const short* fir_input = fir_input_0 + (FIR_KERNEL_SIZE/2);static short        fir_output_expected[FIR_OUTPUT_SIZE];/* This is a trivial JNI example where we use a native method * to return a new VM String. See the corresponding Java source * file located at: * *   apps/samples/hello-neon/project/src/com/example/neon/HelloNeon.java */JNIEXPORT jstring JNICALL Java_com_hello_1neon_android_Hello_1NeonProjectActivity_stringFromJNI(JNIEnv *env, jobject thiz){    char str[512] = {0};    uint64_t features;    char buffer[512];    char tryNeon = 0;    double  t0, t1, time_c, time_neon;    /* setup FIR input - whatever */    {        int  nn;        for (nn = 0; nn < FIR_INPUT_SIZE; nn++) {            fir_input_0[nn] = (5*nn) & 255;        }        fir_filter_c(fir_output_expected, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);    }    /* Benchmark small FIR filter loop - C version */    t0 = now_ms();    {        int  count = FIR_ITERATIONS;        for (; count > 0; count--) {            fir_filter_c(fir_output, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);        }    }    t1 = now_ms();    time_c = t1 - t0;    sprintf(str, "FIR Filter benchmark:\nC version          : %g ms\n", time_c);    strlcpy(buffer, str, sizeof buffer);    strlcat(buffer, "Neon version   : ", sizeof buffer);    if (android_getCpuFamily() != ANDROID_CPU_FAMILY_ARM) {        strlcat(buffer, "Not an ARM CPU !\n", sizeof buffer);        goto EXIT;    }    features = android_getCpuFeatures();    if ((features & ANDROID_CPU_ARM_FEATURE_ARMv7) == 0) {        strlcat(buffer, "Not an ARMv7 CPU !\n", sizeof buffer);        goto EXIT;    }    /* HAVE_NEON is defined in Android.mk ! */#ifdef HAVE_NEON    if ((features & ANDROID_CPU_ARM_FEATURE_NEON) == 0) {        strlcat(buffer, "CPU doesn't support NEON !\n", sizeof buffer);        goto EXIT;    }    /* Benchmark small FIR filter loop - Neon version */    t0 = now_ms();    {        int  count = FIR_ITERATIONS;        for (; count > 0; count--) {            fir_filter_neon_intrinsics(fir_output, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);        }    }    t1 = now_ms();    time_neon = t1 - t0;    sprintf(str, "%g ms (x%g faster)\n", time_neon, time_c / (time_neon < 1e-6 ? 1. : time_neon));    strlcat(buffer, str, sizeof buffer);    /* check the result, just in case */    {        int  nn, fails = 0;        for (nn = 0; nn < FIR_OUTPUT_SIZE; nn++) {            if (fir_output[nn] != fir_output_expected[nn]) {                if (++fails < 16)                    D("neon[%d] = %d expected %d", nn, fir_output[nn], fir_output_expected[nn]);            }        }        D("%d fails\n", fails);    }#else /* !HAVE_NEON */    strlcat(buffer, "Program not compiled with ARMv7 support !\n", sizeof buffer);#endif /* !HAVE_NEON */EXIT:    return env->NewStringUTF(buffer);}#ifdef __cplusplus}#endif


References:

1. http://blog.csdn.net/fengbingchun/article/details/11580983

2. hello-neon example code in android-ndk-r9-windows-x86_64



How to Use Handler in Android

You can directly create your own thread to complete some work.
Handler is mainly used to interact with the main UI thread. For example:
1. You use handler to send a message, and then receive and process the message in the handler thread to avoid affecting other processing tasks of the UI main thread by directly processing transactions in the UI main thread.
2. You can pass the handler object to other processes to send events to you through handler in other processes.
3. You can use handler to send messages in a delayed manner to process some transactions.

Hello, why is the setTitle (Rstringmain_title) statement used in the resource reference in android incorrect?

This kind of error is easy to find. You can check whether there is any resource main_title under String or whether the resource is added to your software. If yes, you can find the id in the R. java file.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.