memcpy 速度太慢?掌握这个技术让内存拷贝效率成倍提升

栏目: IT技术 · 发布时间: 5年前

内容简介:由于并不是所有的armv7架构cpu都支持neon,所以这里增加cpufeatures库用来判断是否支持neon。下面是正确的使用方式。事实上并不是只有arm架构才支持SIMD,x86也是支持的(SSE),并且Android也提供了适用于x86的NEON_2_SSE.h。x86并不直接支持neon指令,而是通过这个头文件将其转为sse指令,以提供与neon相同的api。有兴趣的同学可以研究一下。

封面出自:板栗懒得很

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。有兴趣的同学可以研究一下。


以上所述就是小编给大家介绍的《memcpy 速度太慢?掌握这个技术让内存拷贝效率成倍提升》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入浅出强化学习:原理入门

深入浅出强化学习:原理入门

郭宪、方勇纯 / 电子工业出版社 / 2018-1 / 79

《深入浅出强化学习:原理入门》用通俗易懂的语言深入浅出地介绍了强化学习的基本原理,覆盖了传统的强化学习基本方法和当前炙手可热的深度强化学习方法。开篇从最基本的马尔科夫决策过程入手,将强化学习问题纳入到严谨的数学框架中,接着阐述了解决此类问题最基本的方法——动态规划方法,并从中总结出解决强化学习问题的基本思路:交互迭代策略评估和策略改善。基于这个思路,分别介绍了基于值函数的强化学习方法和基于直接策略......一起来看看 《深入浅出强化学习:原理入门》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

html转js在线工具
html转js在线工具

html转js在线工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具