Android使用neon加速memcpy

作者: Alimin利民 | 来源:发表于2018-09-03 20:06 被阅读9次

  欢迎大家关注一下我开源的一个音视频库,HardwareVideoCodec是一个高效的Android音视频编码库,支持软编和硬编。使用它你可以很容易的实现任何分辨率的视频编码,无需关心摄像头预览大小。一切都如此简单。目前已迭代多个稳定版本,欢迎查阅学习和使用,如有BUG或建议,欢迎Issue。

  memcpy是C/C++的一个标准函数,原型void *memcpy(void *dest, const void *src, size_t n),用于从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
  Neon是适用于ARM Cortex-A系列处理器的一种128位SIMD(Single Instruction, Multiple Data,单指令、多数据)扩展结构。neon支持一次指令处理多个数据,比如处理8个8-bit、4个16-bit、2个32-bit或1个64-bit。正是这个特性可以用于加速内存拷贝。
  在正常情况下memcpy的性能已经足够使用了,但是当我们因为某些原因在拷贝大内存遇到瓶颈的时候,就得使用neon来加速内存拷贝。我是在使用glMapBufferRange把PBO从GPU内存映射到CPU内存的时候遇到了耗时问题,数据大小有921600字节,正常需要6ms就能完成,现在需要30ms。在找不到原因的情况下,暂且使用neon来优化性能。
  在使用neon后,内存拷贝时间也恢复了正常,并且还有2/3的效率提升,能达到4ms。通过汇编代码使用neon是最高效的方式,下面直接上代码。

#ifdef  __ARM__
static void neon_memcpy(volatile unsigned char *dst, volatile unsigned char *src, int sz)
{
    if (sz & 63)
        sz = (sz & -64) + 64;
    asm volatile (
    "NEONCopyPLD: \n"
            " VLDM %[src]!,{d0-d7} \n"
            " VSTM %[dst]!,{d0-d7} \n"
            " SUBS %[sz],%[sz],#0x40 \n"
            " BGT NEONCopyPLD \n"
    : [dst]"+r"(dst), [src]"+r"(src), [sz]"+r"(sz) : : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "cc", "memory");
}
#endif

  Android使用neon需要增加编译参数支持。

#arm架构增加neon支持
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_CFLAGS := -D__cpusplus -g -mfloat-abi=softfp -mfpu=neon -march=armv7-a -mtune=cortex-a8 -DHAVE_NEON=1
endif
#开启两个架构的neon支持(x86可以通过将neon转为sse间接支持)
ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86))
LOCAL_ARM_NEON := true
endif
LOCAL_STATIC_LIBRARIES := cpufeatures

include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures)

  由于并不是所有的armv7架构cpu都支持neon,所以这里增加cpufeatures库用来判断是否支持neon。下面是正确的使用方式。

    #ifdef  __ARM__
        if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
            (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0){//支持NEON
            neon_memcpy(destBuffer, src, length);
        }else{
            memcpy(destBuffer, src, length);
        }
    #else
        //其它架构使用memcpy
        memcpy(destBuffer, src, length);
    #endif

  事实上并不是只有arm架构才支持SIMD,x86也是支持的(SSE),并且Android也提供了适用于x86的NEON_2_SSE.h。x86并不直接支持neon指令,二十通过这个头文件将其转为sse指令,以提供与neon相同的api。有兴趣的童鞋可以研究一下。

相关文章

  • Android使用neon加速memcpy

      欢迎大家关注一下我开源的一个音视频库,HardwareVideoCodec是一个高效的Android音视频编码...

  • Android neon加速优化

    neon是一种SIMD(单指令多数据)指令集,其效率相当于汇编,用于arm cpu平台的优化,在音视频、图形图像处...

  • NEON加速之memcpy在ARM平台的优化

    0x01 前言 系统里面经常需要大量地搬运数据,一般调用的都是memcpy() C库来实现,因此本着“揪牛角尖”的...

  • 使用ARM NEON Intrinsics加速Video Cod

    前言 最近公司在视频直播项目中要使用H.265/HEVC,具体的是使用HW硬件编码H.264/AVC,云端转码成H...

  • GNU C内嵌汇编语言

    大部分的移动端深度学习框架都会使用到neon优化对深度算法的算子进行优化,有些使用了Neon Instructio...

  • Flutter skia

    CPU 渲染称之为软件绘制(关闭硬件加速时使用该引擎,开启硬件加速时使用OpenGL), Android CPU ...

  • C++ 中vector和数组的互相转换

    一. vector转数组: 使用memcpy将vector中的数据拷贝到数组中 注意: memcpy的第三个参数,...

  • Neon指令入门---第一个neon指令程序

    最近工作需要用到neon指令加速模型推理,所以在此记录neon指令的学习过程,一方面加强自己的记忆,另一方面帮助更...

  • memcpy

    memcpy指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝...

  • 个人笔记 - Memcpy

    1.定义 memcpy指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位...

网友评论

    本文标题:Android使用neon加速memcpy

    本文链接:https://www.haomeiwen.com/subject/vyviwftx.html