【代码分享】使用 avx512 + 查表法,优化凯撒加密
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
关于凯撒加密,具体请看:https://en.wikipedia.org/wiki/Caesar_cipher
总而言之就是玩点没什么用的小心眼,把字母的顺序变化一下。
第一版:根据业务逻辑直接实现:
void caesarEncodeV0(uint8_t* out, uint8_t* in, int len, int rot){
rot = rot % 26;
uint8_t* end = in + len;
uint32_t* line = table.Table[rot];
for (;in<end; in++, out++){
if (*in>='a' && *in<='z'){
*out = (*in - 'a' + rot)%26 + 'a';
} else if (*in>='A' && *in<='Z'){
*out = (*in - 'A' + rot)%26 + 'A';
} else {
*out = *in;
}
}
}
void testCaesar(){
const char* s = "QAULi2jah2eqSD1zQAULhuG0Qs9mhOF9TDGtFAGtFqB=";
int len = strlen(s);
uint8_t* out = malloc(len+1);
int rot = 4;
caesarEncodeV0(out, s, len, rot);
out[len] = '\0';
printf("in :%s\n", s);
printf("out:%s | caesarEncodeV0\n", out);
}
第二版:使用查表法
很明显,字符间的替换,可以预先放在一个数组里,然后查表就行了。
typedef struct{
uint32_t Table[26][256]; // uint32_t 要比 uint8_t 更好,猜测是因为字节对齐的原因
} __attribute__((packed)) CaesarTable;
// 预先计算替换规则后的结果
void initTable(uint32_t *table[26][256]){
for (int i=0; i<26; i++){
for (int j=0; j<256; j++){
if (j>='a' && j<='z'){
table[i][j] = (uint8_t)((j-'a'+i)%26 + 'a');
} else if (j>='A' && j<='Z'){
table[i][j] = (uint8_t)((j-'A'+i)%26 + 'A');
} else {
table[i][j] = j;
}
}
}
}
void caesarEncodeV1(uint8_t* out, uint8_t* in, int len, int rot, uint32_t *table[26][256]){
rot = rot % 26;
uint8_t* end = in + len;
uint32_t* line = table[rot];
for (;in<end; in++, out++){
*out = (uint8_t)line[*in]; // 直接查表得到结果
}
}
CaesarTable table;
void testCaesar(){
initTable(&table.Table);
//
const char* s = "QAULi2jah2eqSD1zQAULhuG0Qs9mhOF9TDGtFAGtFqB=";
int len = strlen(s);
uint8_t* out = malloc(len+1);
int rot = 4;
caesarEncodeV1(out, s, len, rot, &table.Table);
out[len] = '\0';
printf("in :%s\n", s);
printf("out:%s | caesarEncodeV1\n", out);
}
第三版:使用 simd,一个周期内查表多次
查看文档发现,只有 avx512 指令集才能很好的支持查表操作。
void caesarEncodeSIMDV2(uint8_t* out, uint8_t* in, int len, int rot, uint32_t *table[26][256]){
rot = rot % 26;
uint32_t* line = table[rot];
const batchSize = 16;
uint8_t* end = in + len - (len&0x0f); // 每个批次处理 16 字节,不够 16 字节的尾部要单独处理
uint8_t* start = in;
for (; start<end; start += batchSize, out += batchSize){
_mm_storeu_epi8( // step5: 把 16 个 int8 存储到目的地址
out, _mm512_cvtepi32_epi8( // step4: 把 16 个 int32 的查表结果,转换成 16 个 int8
_mm512_i32gather_epi32( // step3: 把 16 个 int32 当成偏移量,在 table 开始的地址里面查询. 最后一个参数 4,表示查表中每个元素的偏移量是 4 字节
_mm512_cvtepu8_epi32( // step2: 把 16 个 int8 转换成 16 个 int32
_mm_loadu_si128(start) // step1: 以非对齐的方式,从源地址加载 16 字节
), line, 4))
);
}
end = in + len;
for (; start<end; start++, out++){
*out = (uint8_t)line[*start];
}
}
编译命令行为:
gcc -o caesar caesar.c -g -w -mavx -mavx2 -mavx512f -mavx512vl -mavx512bw -O2
最后测试的结果为:
- 逐个字符查表:67.041 ns/op
- avx512 查表:36.371 ns/op
【代码分享】使用 avx512 + 查表法,优化凯撒加密的更多相关文章
- 经典算法,yuv与rgb互转,查表法,让你的软件飞起来
代码的运算速度取决于以下几个方面 1. 算法本身的复杂度,比如MPEG比JPEG复杂,JPEG比BMP图片的编码复杂. 2. CPU自身的速度和设计架构 3. CPU的总线带宽 4. 您自己代码的写法 ...
- YUV420查表法高效、无失真的转换为RGB32格式
YUV格式有两大类:planar和packed.planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V,这里所讲述的就是这中存储格式的:packed的YUV ...
- C#,Java,C -循环冗余检验:CRC-16-CCITT查表法
C#代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ...
- 查表法计算CRC16校验值
CRC16是单片机程序中常用的一种校验算法.依据所采用多项式的不同,得到的结果也不相同.常用的多项式有CRC-16/IBM和CRC-16/CCITT等.本文代码采用的多项式为CRC-16/IBM: X ...
- 【C语言学习笔记】空间换时间,查表法的经典例子!知识就是这么学到的~
我们怎么衡量一个函数/代码块/算法的优劣呢?这需要从多个角度看待.本篇笔记我们先不考虑代码可读性.规范性.可移植性那些角度. 在我们嵌入式中,我们需要根据实际资源的情况来设计我们的代码.比如当我们能用 ...
- C语言:十进制进制转换为其他进制(思想:查表法)
// // main.c // Hex conversion // // Created by ma c on 15/7/22. // Copyright (c) 2015年 bjsxt. A ...
- 最简单的CRC32源码-查表法
这个算法是在逐BYTE法的基础上进行修改的,在上一篇文章里我们说过,如果不查表的话,逐BYTE法和逐BIT法没什么区别,现在我们就把这个算法写出来,注意在调用CRC校验函数前需要先调用表生成函数: u ...
- 嵌入式C语言查表法的项目应用
嵌入式C实战项目开发技巧:如果对一个有规律的数组表进行位移操作 就像下面的这个表 之前写过上面这个标题的一篇文章,讲的是以位移的方式去遍历表中的数据,效率非常高,但是,如果要实现一个乱序的流水灯或者跑 ...
- 嵌入式C语言查表法
转自:https://blog.csdn.net/morixinguan/article/details/51799668 作者:Engineer-Bruce_Yang 就像下面的这个表 之前写 ...
- RGB2GRAY 各种算法速度比较,整形乘法比查表法快!
1. 查表法,外循环用 这种格式 : //for(int j = 0; j != h; ++j)// for(int i = 0; i!=w;++i)//. for(int j = 0; j != ...
随机推荐
- 查询速度最高提升50倍!火山引擎ByteHouse在广告投放领域实践分享
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 据QuestMobile报告显示,移动互联网已经进入了下半场,在使用人数和使用时长方面已经没有明显增长,互联 ...
- 用 docker 部署 folkmq 消息中间件
docker run -p 18602:18602 -p 8602:8602 noearorg/folkmq-server:1.0.19
- Linux系统用户态和内核态
Unix/Linux的体系架构 如上图所示,从宏观上来看,Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核空间).内核从本质上看是一种软件-----控制计算机的硬件资源,并提供上层应 ...
- 基于Kresling折纸结构双稳态空间的无人机着陆系统新结构
摘要:本文利用动捕技术对无人机着陆系统模型进行动力学分析,对折纸结构双稳态着陆系统性能进行测试,为无人机着陆系统结构设计提供创新方法. 近期,一篇关于无人机着陆系统的研究论文"Evoluti ...
- POJ 1456 Supermarket【贪心 + 并查集】
http://poj.org/problem?id=1456 题意:给你 N 件不同的商品,每件商品最多可以买一次.每件物品对应两个值 pi di pi 表示物品的价值,di 表示可以买的最迟时间(也 ...
- [VS Code] 入门-自定键盘快捷键
Keyboard Shortcuts 自訂鍵盤快捷鍵 開啟設定面板 :點擊左下角管理圖示〉選擇「鍵盤快速鍵」. 編輯器開啟後,滑鼠移至變更項目上,點擊出現的變更圖示(橘框處),輸入要變更的快捷鍵組合. ...
- 红黑树是什么?红黑树 与 B+树区别和应用场景?
红黑树是什么?怎么实现?应用场景? 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉树. 意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键值,小 ...
- Xmanager连接linux服务器的桌面
在办公室使用xshell通过22端口访问linux服务器大家都很熟悉,但有的时候在办公室要远程linux服务器上的桌面应用,该如何实现. 环境准备 客户端:win10 服务器:centos7.9 一. ...
- 一次完整的HTTP服务过程
- freeswitch的mod_xml_curl模块
概述 freeswitch是一款简单好用的VOIP开源软交换平台. 随着fs服务的增多,每一台fs都需要在后台单独配置,耗时耗力,心力憔悴. 如果有一个集中管理配置的配置中心,统一管理所有fs的配置, ...
