11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

如何使用 SSE2 指令集加速字符替换

  • 2020-03-20
  • 本文字数:1054 字

    阅读完需:约 3 分钟

如何使用SSE2指令集加速字符替换

导语

我们在写代码的时候,在字符串处理的时候,可能会遇到这样的需求,就是把一个目标字符串中所有出现的某个字符 a 替换为另外一个字 c.


比如对于 Yaf_Loader 中,在处理命名空间的类名的自动加载的时候,我需要把所有的 \ 替换为 _ ,一般通常的写法会是:



SSE2 如何加速

而目前 SIMD 指令的支持已经非常普遍,尤其 SSE2,基本当代的 CPU 都支持, 可以通过 cat /proc/cpuinfo 来看 cpu 支持的 SIMD 指令集:



可见我的这个 CPU 支持 mmxssesse2ssse3sse4.1sse4.2avx.


回到正题,我们知道 SIMD 128 指令集可以一次处理 16 个字符,上面的代码可以通过如下代码来等效实现:



这里面核心的代码部分是:



我来一行一行解释,假设我们现在要处理的字符串是"G\Namespace\package\classname


  • 第一行:拿 16 个字符和字符 ‘\’ 做比较,如果某位相等,则 16 位结果中对应的 byte 就为 0xff(-1),否则就为 0,那么对于:


  • 来说,会得到结果:


  • 第二行:如果对比的结果不全为零的话,就进行到这行,这行的核心思想是因为 ascii 码 ‘_’(95)‘\’(92) 之间差了 3,所以我们通过and指令得到如下结果:


  • 第三行:我们把刚刚的 delta 结果加回到原始字符串中去,也就是:


  • 第四行:把结果写回内存


总结

这样一来,我就可以用一条指令同时检测 16 个字符,效率会大大提升。我们来做个简单的测试,测试脚本在这里是:replace_chr.c(阅读原文可见)


下载下来以后,用 -O2 编译,在我的开发机上跑的结果是(结果会根据字符串中出现 ‘\’ 的位置和数量不同而有些许差异):



从结果上可以看到,在字符串长度小于 16 的时候,SSE2 版本的速度略逊于普通版本,但是当字符串长度大于 16 以后,SSE2 的版本的优势就非常明显了。


附言

与其说是针对这个特定的字符替换的问题,我其实更主要对是想分享这种使用 SIMD 解决问题的思路,如何把类似的问题抽象为这样的”批量操作”。比如在之前在开发 PHP7 的时候,我也为 PHP7 引入过采用 SIMD 指令来实现快速的base64_encode/decode函数,这个性能提升很明显,因为被操作的字符串一般都很长,有兴趣的伙伴可以参看 Base64 Encode with SSSE3(阅读原文可见) , 以后有机会也可以分享下那个例子是怎么做的。


最后,关于 SIMD 指令集的速查,可以看这里:Intel Intrinsics Guide


本文转载自公众号贝壳产品技术。


原文链接


https://mp.weixin.qq.com/s?__biz=MzIyMTg0OTExOQ==&mid=2247485398&idx=1&sn=f698839b2c54609d7d0b27dc7b43fa1a&chksm=e83734a6df40bdb0f08249a69252db4bb7c758158ff243ce03e99fe2333780f9ca2268712370&scene=27#wechat_redirect


2020-03-20 14:001456

评论 2 条评论

发布
用户头像
一个潜在的要求是 pos初始值必须16位对齐,有没有考虑
2020-06-28 00:19
回复
loadu 不需要16位内存对齐
2020-06-29 18:39
回复
没有更多了
发现更多内容

@全体开发者, 华为云1024程序员节精彩开启!

华为云开发者联盟

华为云 企业号十月 PK 榜

从零手写react-router

helloworld1024fd

JavaScript

长安链源码分析之网络模块 net-liquid(4)

时间复杂度与空间复杂度

lovevivi

c 数据结构 10月月更

vcluster -- 基于虚拟集群的多租户方案

Se7en

Kubernetes 云原生

一句口诀教你辨别索引失效七大场景

华为云开发者联盟

数据库 后端 索引 华为云 企业号十月 PK 榜

前端培训学习好就业吗?

小谷哥

前端编程培训学习就业有前途吗?

小谷哥

开源依赖管理的最佳实践

SEAL软件供应链安全

开源许可证 开源安全 软件供应链安全 开源安全与治理 10月月更

云图说|AppCube零代码,开启无码新生活

华为云开发者联盟

低代码 零代码 华为云 企业号十月 PK 榜

ThreadLocal 源码分析-扩容和get方法

zarmnosaj

10月月更

数据结构学习,数组和数组矩阵的三种压缩

IC00

学习 数据结构 算法 学习笔记 10月月更

大数据开发培训机构有哪些?

小谷哥

数字化的一切都会在安全沙箱里面

FN0

云计算 安全性 沙箱

K8S 故障排错新手段:kubectl debug实战

BoCloud博云

容器 云原生 k8s

js 和 css 是如何影响DOM树构建的?

CoderBin

CSS JavaScript 前端 DOM 10月月更

C# Timer控件学习,使用Timer解决按钮幂等性问题

IC00

C# 学习 程序员 上位机 10月月更

音视频开发进阶——YUV与RGB的采样与存储格式

ZEGO即构

音视频开发

AntDB数据并行加载工具的实现

亚信AntDB数据库

大数据 AntDB AntDB数据库 企业号十月PK榜 企业号十月 PK 榜

插件数据集打开API网关插件体系的想象力

阿里云E2企业云服务

前端 服务器 插件 API api 网关

社招前端经典手写面试题合集

helloworld1024fd

JavaScript

从零开始实现一个Promise

helloworld1024fd

JavaScript

质量切入点都在哪儿呢?

QE_LAB

质量保障 敏捷精益

需求吞吐量半年提升 65%,500强企业这样做|ONES 研发管理大师课

万事ONES

web前端开发培训学习合适吗?

小谷哥

如何使用SSE2指令集加速字符替换_硬件_惠新宸(鸟哥)_InfoQ精选文章