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

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

内容简介:由于并不是所有的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 速度太慢?掌握这个技术让内存拷贝效率成倍提升》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Foundations of PEAR

Foundations of PEAR

Good, Nathan A./ Kent, Allan / Springer-Verlag New York Inc / 2006-11 / $ 50.84

PEAR, the PHP Extension and Application Repository, is a bountiful resource for any PHP developer. Within its confines lie the tools that you need to do your job more quickly and efficiently. You need......一起来看看 《Foundations of PEAR》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具