封面出自:板栗懒得很

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字节的数据需要30ms,在使用neon后,内存拷贝耗时直接降低到了4ms,相差将近8倍。事实上,在arm平台上使用neon指令可以高效提升数据并行处理性能,而不仅仅局限于内存拷贝。google开源的libyuv内部也使用了neon指令来并行处理数据。

使用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

由于并不是所有的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

Android mk开启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)

Cmake开启neon

# 引入cpufeatures模块

include_directories(${ANDROID_NDK}/sources/android/cpufeatures)

if (${ANDROID_ABI} STREQUAL "armeabi-v7a")

set_property(SOURCE ${SOURCES} APPEND_STRING PROPERTY COMPILE_FLAGS " -mfpu=neon")

add_definitions("-DHAVE_NEON=1")

elseif (${ANDROID_ABI} STREQUAL "x86")

set_property(SOURCE ${SOURCES} APPEND_STRING PROPERTY COMPILE_FLAGS

" -mssse3 -Wno-unknown-attributes \

-Wno-deprecated-declarations \

-Wno-constant-conversion \

-Wno-static-in-inline")

add_definitions(-DHAVE_NEON_X86=1 -DHAVE_NEON=1)

endif ()

add_library(

yourLibrary

SHARED

${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c

)

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

Android显存到内存拷贝耗时,memcpy速度太慢?掌握这个技术让内存拷贝效率成倍提升...相关推荐

  1. 抖音android x86,抖音数据采集教程,详解Hook框架frida,让你在逆向工作中效率成倍提升!...

    免责声明:本文档仅供学习与参考,请勿用于非法用途!否则一切后果自负. 一.frida简介frida是一款基于python + java 的hook框架,可运行在androidioslinuxwinos ...

  2. 实现一个高效率的内存拷贝函数memcpy

    内存拷贝函数memcpy memcpy是memory copy的缩写,意为内存复制,在写C语言程序的时候,我们常常会用到它.它的函原型如下: void *memcpy(void *dest, cons ...

  3. 内存拷贝函数memcpy相关解析(C语言)

    memcpy方法解析 内存拷贝函数的一般用法 memcpy()函数的拷贝原理分析 以深浅拷贝为例分析memcpy的拷贝原理 用memcpy()函数与不用memcpy()函数进行拷贝数据的区分 内存拷贝 ...

  4. 字符串复制函数strncpy()和内存拷贝函数memcpy()

    #include<string.h> char *strncpy(char *dest, const char *src, unsigned long n); 功能是将指针变量src所指向 ...

  5. 带权限后台拷贝小文件速度

    背景 前几个月在客户处测试异构存储之间进行带权限的后台CIFS文件迁移.本文记录对于小文件场景下文件拷贝速度的认知. 迁移软件介绍 1.Hitachi Compliant Migration Tool ...

  6. 【Android 内存优化】内存抖动 ( 垃圾回收算法总结 | 分代收集算法补充 | 内存抖动排查 | 内存抖动操作 | 集合选择 )

    文章目录 一. 垃圾回收算法总结 二. 分代收集算法补充 三. 查看 Java 虚拟机 四. 获取 Android 应用可使用最大内存 五. 内存抖动标志 六. 排查内存抖动 七. 常见的造成内存抖动 ...

  7. 安卓接受后台数据转换解析出错_安卓手机内存越大,速度就会越快?

    与非网 2 月 18 日讯,现在安卓手机的内存在产品规划上越来越大,2020 年发布的旗舰手机运行内存已经拓展到惊人的 10GB 以上,而这个运存大小已经超过笔记本主流的 8GB 内存,手机到底需要这 ...

  8. linux利用内存加快读盘速度,Linux性能优化从入门到实战:10 内存篇:如何利用Buffer和Cache优化程序的运行效率?...

    缓存命中率 缓存命中率,是指直接通过缓存获取数据的请求次数,占所有数据请求次数的百分比,可以衡量缓存使用的好坏.命中率越高,表示使用缓存带来的收益越高,应用程序的性能也就越好. 实际上,缓存是现在所有 ...

  9. Android内存(RAM)大小信息查看、获取方法和内存分配方法

    内存信息查看 Android手机的内存大小信息存放在手机系统的 /proc/meminfo 文件里面,我们可以通过读取这个文件来获取内存信息. 使用 cmd 命令行打开终端或直接在 Android S ...

最新文章

  1. tf.keras.layers.Conv2D 示例
  2. 【Linux】ubuntu系统VMware Tools(文件共享、全屏...)3步完成安装过程亲测可用
  3. storm 简介及单机版安装指南
  4. java调C接口_java通过jni调用C程序接口
  5. 终于有人把tomcat讲清楚了。
  6. Netty服务端口的绑定
  7. sublime番外篇:入门者食用指北
  8. 阿里企业邮箱产品优势、功能、版本介绍
  9. HDUOJ_2567_寻梦
  10. 64位ubuntu使用gcc -m32报错
  11. Markdown Day01
  12. 达芬奇大王的链表贪吃蛇(java)
  13. 有效前沿和最优投资组合matlab,matlab 实验名称:投资组合分析 实验性质:综合性和研究探索性 实 联合开发网 - pudn.com...
  14. OpenSSL DTLS通信(一)
  15. hp服务器看网卡位置,HP SuperDome确定网卡所在物理位置的方法:
  16. .zip.001 .zip.002怎么用压缩包解压缩?
  17. 通过kafka和filebeat收集日志 再保存到clickhouse 最后通过grafana展现
  18. 金融科技的下半场:服务边界的“进化论”
  19. 解决上传图片时报错Uncaught (in promise) DOMException: Failed to execute ‘put‘ on ‘IDBObjectStore‘
  20. 现在武汉的每套房屋将有“身份证号”

热门文章

  1. JVM内存溢出时快照转存HeapDump到文件
  2. Web API 2 入门——创建ASP.NET Web API的帮助页面(谷歌翻译)
  3. ASP.NET系统退出(移除Session 、清除浏览器缓存)
  4. 【原】npm 常用命令详解
  5. 进制A~Z,全字母26进制转化
  6. WebView退出时停止视频播放
  7. Delphi下物理删除dBase数据库的*.dbf文件
  8. 手把手教你|拦截系统调用
  9. 分享GitHub上一些嵌入式相关的高星开源项目
  10. Datawhale-零基础入门NLP-新闻文本分类Task03