memcpy 速度太慢?掌握这个技术让内存拷贝效率成倍提升
source link: https://mp.weixin.qq.com/s?__biz=MzA4MjU1MDk3Ng%3D%3D&%3Bmid=2451526913&%3Bidx=1&%3Bsn=f9c647604c97f116eaf7fac6e6af0b7e&%3Bchksm=886ffcaebf1875b84bc7fc6edbab3962230ecd919f915d3fe11c56f2591eb3fc213c6ebc446b&%3Btoken=2044115023&%3Blang=zh_CN
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
封面出自:板栗懒得很
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。有兴趣的同学可以研究一下。
Recommend
-
114
升级 iOS 11 后,iPhone 用户抱怨速度太慢、性能降低_详细解读_最新资讯_热点事件_36氪升级 iOS 11 后,iPhone 用户抱怨速度太慢、性能降低神译局20...
-
45
导读 我们在搞清楚如何加速Linux计算机之前,需要知道哪些方法可以帮助我们找到引导时启动的服务、以更高或更低优先级运行的进程、CPU运行状况、内存是否塞满了过多数据,还要检查交换内存区是否已满。最后,我...
-
38
在国内,你们肯定发现使用git clone的速度实在太慢,git clone的速度可能会让你难以承受,现再次整理解决方法与大家分享,有图有真相。
-
12
嫌 OSS 查询太慢?看我们如何将速度提升 10 倍!丁凯工程师,期望当一个坐台歌手,个人主页:www.d-kai.me
-
6
TJ君最近有点惆怅,为啥呢?最近TJ君发现GitHub越来越难上了,有时候经常出现无法访问的情况: 想必很多人也会跟TJ君有同样的烦恼,毕竟GitHub是一个学习编程的好地方,这样断断续续的使用,极度影响吾等程序猿的用户体验,那,该怎么办!? 既然...
-
58
sdkman 下载 jdk 速度太慢,怎么破有没有国内的源可以用 V2EX › 程序员 sdkman 下载 jdk 速度太慢,怎么破有没有国内的源...
-
6
计算速度太慢?试试 lru_cache 装饰器发布于 今天 14:14 众所周知,python语言是相当好用的,但是它的执行性能也是相对其他语言比较慢的。还好python提供了一个非常...
-
5
TienChin 项目也是一个前后端分离项目,前后端分离项目如果做成 SPA(单页面)的形式,就必然面临一个首屏加载的问题,因为默认情况下首页文件比较大,可能超过 1 MB,进而带来首页加载很慢的问题。所以我们要通过优化,来提高首页的加载速度。问题的解决,一...
-
3
比memcpy还要快的内存拷贝,了解一下? 本文来自博客园,...
-
5
小鸡搭的机场速度太慢怎么解决 - V2EX V2EX › VPS 小鸡搭的机场速...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK