【代码分享】使用 avx2 + 查表法,优化凯撒加密
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
接上一篇:【代码分享】使用 avx512 + 查表法,优化凯撒加密
好不容易捣鼓出来了 avx512 指令集的查表法代码,可是部署的时候发现服务器不支持 avx512 指令集。
终于,avx2 版本的查表法终于写出来了。上代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <immintrin.h>
#include <avx2intrin.h>
#include <inttypes.h>
#include <assert.h>
typedef uint32_t Table[26][256];
void initTable(Table *table){
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 caesarEncodeAVX2(void* out1, void* in1, uint64_t len, uint64_t rot, void* table1){
uint8_t* out = (uint8_t*)out1;
uint8_t* in = (uint8_t*)in1;
Table* table = (Table*)table1; // 这些代码为了解决 cgo 中函数调用的警告
//
rot = rot % 26;
uint32_t* line = (uint32_t*)((*table)[rot]);
#define batchSize 16
uint64_t tailLen = len & 0x0f;
uint8_t* end = in + len - tailLen;
uint8_t* start = in;
const __m256i index_mask = _mm256_set_epi32(
7, 6, 3, 2,
5,4, 1, 0
);
for (; start<end; out += batchSize, start += batchSize){
__m128i src = _mm_loadu_si128(start); // 加载 16 个字符,但只处理前面 8 个字符
__m256i srcI32 = _mm256_cvtepu8_epi32(src); // 前 8 个字节,转换为 32 字节
__m256i foundHead = _mm256_i32gather_epi32(line, srcI32, 4); // 8 字节查表
// 处理后面 8 字节
src = _mm_srli_si128(src, 8); // 移动 8 字节,也就是 64 位
srcI32 = _mm256_cvtepu8_epi32(src); // 后 8 个字节,转换为 32 字节
__m256i foundTail = _mm256_i32gather_epi32(line, srcI32, 4); // 8 字节查表
// 进行压缩
__m256i found16 = _mm256_packus_epi32(foundHead, foundTail); // 16 个 16 位的值
/*
_mm256_packus_epi32 这个指令非常的恶心:aaaa bbbb 合并成了 aa bb aa bb
于是还要用下面这个指令把顺序换过来
*/
found16 = _mm256_permutevar8x32_epi32 (found16, index_mask); // 换过来了,正常了
found16 = _mm256_packus_epi16(found16, _mm256_setzero_si256());
found16 = _mm256_permutevar8x32_epi32 (found16, index_mask); // 换过来了,正常了
//存储
__m128i result = _mm256_castsi256_si128(found16);
_mm_storeu_si128 (out, result);
}
//
end = in + len;
for (; start<end; start++, out++){
*out = (uint8_t)line[*start];
}
}
// 逐字节处理的版本
void caesarEncode(uint8_t* out, uint8_t* in, int len, int rot, Table* t){
rot = rot % 26;
uint8_t* end = in + len;
uint32_t* line = (uint32_t*)((*t)[rot]);
for (;in<end; in++, out++){
*out = (uint8_t)line[*in];
}
}
编译:
gcc -o caesar caesar.c -g -w -mavx -mavx2 -O3
测试了一下各个版本的性能表现:
逐字节处理版本:total:201429 us, avg: 100.715 ns/op
AVX2 版本: total:51059 us, avg: 25.529 ns/op
AVX512 版本: total:49756 us, avg: 24.878 ns/op
avx512 版本只比 avx2 快了一点点,鸡肋!
【代码分享】使用 avx2 + 查表法,优化凯撒加密的更多相关文章
- 经典算法,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 != ...
随机推荐
- PPT 产品发布会PPT应该怎么样改
PPT 毕业答辩PPT应该怎么样改 大图背景打底 刺眼 收集素材
- 使用 Kubeadm 部署 Kubernetes(K8S) 安装 -- 持久化存储(PV&PVC)
使用 Kubeadm 部署 Kubernetes(K8S) 安装 -- Ingress-Ngnix 使用 Kubeadm 部署 Kubernetes(K8S) 安装 -- 持久化存储(NFS网络存储) ...
- Go--记录下踩map的坑
这两天新调个接口的时候,一直提示签名错误,但所需的时间,工号,token都是对的,完全没有头绪,卡了两天后,终于找到原因了 原因是我的校验信息,是要将时间,工号,token封装在一起成字符串,然后用m ...
- AtCoder Beginner Contest 180 个人题解(快乐DP场)
补题链接:Here A - box 输出 \(N - A + B\) B - Various distances 按题意输出 3 种距离即可 #include <bits/stdc++.h> ...
- 十三、docker的四种网络类型
系列导航 一.docker入门(概念) 二.docker的安装和镜像管理 三.docker容器的常用命令 四.容器的网络访问 五.容器端口转发 六.docker数据卷 七.手动制作docker镜像 八 ...
- Linux一键安装docker脚本,含ubuntu和centos
将脚本保存为docker_install.sh,可以上传git,到服务器中,git clone下来后,sh docker_install.sh即可自动安装 ubuntu实现 # 以Ubuntu为例 # ...
- HUD 5773 LIS(最长上升序列)
***关于lower_bound()的用法参见:http://blog.csdn.net/niushuai666/article/details/6734403 lower_bound用法:函数low ...
- Liunx常用操作(三)-如何忽略大小写查找
1.vim 中的查找 搜索文件内容时加上 /c 参数可以忽略搜索字符的大小写 正常搜索:/helloworld 忽略操作:/helloworld/c 2.find 查找 使用find命令搜索文件时如果 ...
- python常见面试题讲解(五)质数因子
题目描述 功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 ) 最后一个数后面也要有空格 输入描述: 输入一个long型整数 输出描述 ...
- 用C#实现最小二乘法(用OxyPlot绘图)✨
最小二乘法介绍 最小二乘法(Least Squares Method)是一种常见的数学优化技术,广泛应用于数据拟合.回归分析和参数估计等领域.其目标是通过最小化残差平方和来找到一组参数,使得模型预测值 ...
