作者:张富春(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 + 查表法,优化凯撒加密的更多相关文章

  1. 经典算法,yuv与rgb互转,查表法,让你的软件飞起来

    代码的运算速度取决于以下几个方面 1. 算法本身的复杂度,比如MPEG比JPEG复杂,JPEG比BMP图片的编码复杂. 2. CPU自身的速度和设计架构 3. CPU的总线带宽 4. 您自己代码的写法 ...

  2. YUV420查表法高效、无失真的转换为RGB32格式

    YUV格式有两大类:planar和packed.planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V,这里所讲述的就是这中存储格式的:packed的YUV ...

  3. C#,Java,C -循环冗余检验:CRC-16-CCITT查表法

    C#代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ...

  4. 查表法计算CRC16校验值

    CRC16是单片机程序中常用的一种校验算法.依据所采用多项式的不同,得到的结果也不相同.常用的多项式有CRC-16/IBM和CRC-16/CCITT等.本文代码采用的多项式为CRC-16/IBM: X ...

  5. 【C语言学习笔记】空间换时间,查表法的经典例子!知识就是这么学到的~

    我们怎么衡量一个函数/代码块/算法的优劣呢?这需要从多个角度看待.本篇笔记我们先不考虑代码可读性.规范性.可移植性那些角度. 在我们嵌入式中,我们需要根据实际资源的情况来设计我们的代码.比如当我们能用 ...

  6. C语言:十进制进制转换为其他进制(思想:查表法)

    // //  main.c //  Hex conversion // //  Created by ma c on 15/7/22. //  Copyright (c) 2015年 bjsxt. A ...

  7. 最简单的CRC32源码-查表法

    这个算法是在逐BYTE法的基础上进行修改的,在上一篇文章里我们说过,如果不查表的话,逐BYTE法和逐BIT法没什么区别,现在我们就把这个算法写出来,注意在调用CRC校验函数前需要先调用表生成函数: u ...

  8. 嵌入式C语言查表法的项目应用

    嵌入式C实战项目开发技巧:如果对一个有规律的数组表进行位移操作 就像下面的这个表 之前写过上面这个标题的一篇文章,讲的是以位移的方式去遍历表中的数据,效率非常高,但是,如果要实现一个乱序的流水灯或者跑 ...

  9. 嵌入式C语言查表法

    转自:https://blog.csdn.net/morixinguan/article/details/51799668    作者:Engineer-Bruce_Yang 就像下面的这个表 之前写 ...

  10. RGB2GRAY 各种算法速度比较,整形乘法比查表法快!

    1.  查表法,外循环用 这种格式 :  //for(int j = 0; j != h; ++j)// for(int i = 0; i!=w;++i)//. for(int j = 0; j != ...

随机推荐

  1. 手把手带你玩转LiteOS Ping组件

    摘要:本期小编为大家带来LiteOS开源版本Ping组件的使用说明,请跟随小编的步伐一起进入探索之旅吧! 本文分享自华为云社区<LiteOS组件尝鲜-玩转Ping>,作者:Lionlace ...

  2. 敏捷开发专家一席谈:云原生技术下的华为云DevOps实践之路

    摘要:听华为云DevCloud首席技术布道师徐毅讲述云原生下的DevOps实践. 本文分享自华为云社区<敏捷开发专家一席谈:云原生技术下的华为云DevOps实践之路>,作者:华为云社区精选 ...

  3. 性能持续突破!火山引擎ByteHouse上线向量检索能力

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   随着LLM技术应用及落地,数据库需要提高向量分析以及AI支持能力,向量数据库及向量检索等能力"异军突 ...

  4. 挖掘优质短视频超百万条,火山引擎DataLeap助力电商平台生态治理

     更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   在人们的日常生活中,网购已经成为人们生活中不可或缺的购物形式.   根据<中国社交电商行业发展白皮书( ...

  5. 多领域应用落地,火山引擎ByteHouse加速云数仓升级

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   近日,火山引擎数智平台VeDI直播活动「超话数据」在线举办,来自火山引擎的产品及解决方案专家分享了以ByteH ...

  6. 【Qt Libraries】QUrl 的基本使用方法

    参考博客: https://www.cnblogs.com/liushui-sky/p/10892097.html https://www.cnblogs.com/ShineLeBlog/p/1495 ...

  7. AtCoder Educational DP Contest 刷题记录

    写在前面 深感自己 DP 很弱的 村人B 刷了点 DP 题,题集地址戳这里. 后记:刷完后感觉自己又行了 A - Frog 1 题意 给定 \(n\) 个石头,第 i 个石头的高度为 \(h_i\). ...

  8. AtCoder Beginner Contest 208 A~E个人题解

    比赛链接:Here A - Rolling Dice 水题 一个六面的骰子,请问摇动 \(A\) 次最后的点数和能否为 \(B\) 如果 \(B \in [a,6a]\) 输出 YES C++ voi ...

  9. vivo 全球商城:订单中心架构设计与实践

    一.背景 随着用户量级的快速增长,vivo 官方商城 v1.0 的单体架构逐渐暴露出弊端:模块愈发臃肿.开发效率低下.性能出现瓶颈.系统维护困难. 从2017年开始启动的 v2.0 架构升级,基于业务 ...

  10. SpringBoot Serverless 实战 | 监控调试

    SpringBoot 是基于 Java Spring 框架的套件,它预装了 Spring 的一系列组件,让开发者只需要很少的配置就可以创建独立运行的应用程序.在云原生的世界,有大量的平台可以运行 Sp ...