dalek-Curve25519 avx2并行计算学习笔记

2023-10-24 15:30

本文主要是介绍dalek-Curve25519 avx2并行计算学习笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 引言

Curve25519 Field Element在有限域 2 255 − 19 2^{255}-19 225519域内,采用64bit 串行计算时,采用的是5个FieldElement51元素来表示一个Element;若采用32-bit AVX2并行计算,则每个Element由10个FieldElement2526元素来表示。
即对于某Curve25519 Field Element a,对应的32-bit AVX2表示为(其中 若 i % 2 = = 0 , a i &lt; 2 26 &lt; 2 32 ; e l s e a i &lt; 2 25 &lt; 2 32 若\ i\%2==0,\ a_i&lt;2^{26}&lt;2^{32}; else\ a_i&lt;2^{25}&lt;2^{32}  i%2==0, ai<226<232;else ai<225<232):

a 9 a_9 a9 a 8 a_8 a8 a 7 a_7 a7 a 6 a_6 a6 a 5 a_5 a5 a 4 a_4 a4 a 3 a_3 a3 a 2 a_2 a2 a 1 a_1 a1 a 0 a_0 a0
/// Given an array of wide coefficients, reduce them to a `FieldElement2625x4`.////// # Postconditions////// The coefficients of the result are bounded with \\( b < 0.007 \\).#[inline]fn reduce64(mut z: [u64x4; 10]) -> FieldElement2625x4 {// These aren't const because splat isn't a const fnlet LOW_25_BITS: u64x4 = u64x4::splat((1 << 25) - 1);let LOW_26_BITS: u64x4 = u64x4::splat((1 << 26) - 1);// Carry the value from limb i = 0..8 to limb i+1let carry = |z: &mut [u64x4; 10], i: usize| {debug_assert!(i < 9);if i % 2 == 0 {// Even limbs have 26 bitsz[i + 1] = z[i + 1] + (z[i] >> 26);z[i] = z[i] & LOW_26_BITS;} else {// Odd limbs have 25 bitsz[i + 1] = z[i + 1] + (z[i] >> 25);z[i] = z[i] & LOW_25_BITS;}};// Perform two halves of the carry chain in parallel.carry(&mut z, 0); carry(&mut z, 4);carry(&mut z, 1); carry(&mut z, 5);carry(&mut z, 2); carry(&mut z, 6);carry(&mut z, 3); carry(&mut z, 7);// Since z[3] < 2^64, c < 2^(64-25) = 2^39,// so    z[4] < 2^26 + 2^39 < 2^39.0002carry(&mut z, 4); carry(&mut z, 8);// Now z[4] < 2^26// and z[5] < 2^25 + 2^13.0002 < 2^25.0004 (good enough)// Last carry has a multiplication by 19.  In the serial case we// do a 64-bit multiplication by 19, but here we want to do a// 32-bit multiplication.  However, if we only know z[9] < 2^64,// the carry is bounded as c < 2^(64-25) = 2^39, which is too// big.  To ensure c < 2^32, we would need z[9] < 2^57.// Instead, we split the carry in two, with c = c_0 + c_1*2^26.let c = z[9] >> 25;z[9] = z[9] & LOW_25_BITS;let mut c0: u64x4 = c & LOW_26_BITS; // c0 < 2^26;let mut c1: u64x4 = c >> 26;         // c1 < 2^(39-26) = 2^13;unsafe {use core::arch::x86_64::_mm256_mul_epu32;let x19 = u64x4::splat(19);c0 = _mm256_mul_epu32(c0.into_bits(), x19.into_bits()).into_bits(); // c0 < 2^30.25c1 = _mm256_mul_epu32(c1.into_bits(), x19.into_bits()).into_bits(); // c1 < 2^17.25}z[0] = z[0] + c0; // z0 < 2^26 + 2^30.25 < 2^30.33z[1] = z[1] + c1; // z1 < 2^25 + 2^17.25 < 2^25.0067carry(&mut z, 0); // z0 < 2^26, z1 < 2^25.0067 + 2^4.33 = 2^25.007// The output coefficients are bounded with//// b = 0.007  for z[1]// b = 0.0004 for z[5]// b = 0      for other z[i].//// So the packed result is bounded with b = 0.007.FieldElement2625x4([repack_pair(z[0].into_bits(), z[1].into_bits()),repack_pair(z[2].into_bits(), z[3].into_bits()),repack_pair(z[4].into_bits(), z[5].into_bits()),repack_pair(z[6].into_bits(), z[7].into_bits()),repack_pair(z[8].into_bits(), z[9].into_bits()),])}

2. vector (a,b,c,d)表示

根据博客CPU指令集——AVX2第四节内容有:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
所以有:
在这里插入图片描述
对于4 field elements vector ( a , b , c , d ) (a,b,c,d) (a,b,c,d)可以 [ u 32 × 8 ; 5 ] [u32\times8;5] [u32×8;5]数组(以little-endian形式)来表示:
( a 0 , b 0 , a 1 , b 1 , c 0 , d 0 , c 1 , d 1 ) (a_0,b_0,a_1,b_1,c_0,d_0,c_1,d_1) (a0,b0,a1,b1,c0,d0,c1,d1)
( a 2 , b 2 , a 3 , b 3 , c 2 , d 2 , c 3 , d 3 ) (a_2,b_2,a_3,b_3,c_2,d_2,c_3,d_3) (a2,b2,a3,b3,c2,d2,c3,d3)
( a 4 , b 4 , a 5 , b 5 , c 4 , d 4 , c 5 , d 5 ) (a_4,b_4,a_5,b_5,c_4,d_4,c_5,d_5) (a4,b4,a5,b5,c4,d4,c5,d5)
( a 6 , b 6 , a 7 , b 7 , c 6 , d 6 , c 7 , d 7 ) (a_6,b_6,a_7,b_7,c_6,d_6,c_7,d_7) (a6,b6,a7,b7,c6,d6,c7,d7)
( a 8 , b 8 , a 9 , b 9 , c 8 , d 8 , c 9 , d 9 ) (a_8,b_8,a_9,b_9,c_8,d_8,c_9,d_9) (a8,b8,a9,b9,c8,d8,c9,d9)

亦即对于4 field elements vector ( a , b , c , d ) (a,b,c,d) (a,b,c,d),可以FieldElement2625x4表示为:

/// A vector of four field elements.
///
/// Each operation on a `FieldElement2625x4` has documented effects on
/// the bounds of the coefficients.  This API is designed for speed
/// and not safety; it is the caller's responsibility to ensure that
/// the post-conditions of one operation are compatible with the
/// pre-conditions of the next.
#[derive(Clone, Copy, Debug)]
pub struct FieldElement2625x4(pub(crate) [u32x8; 5]);

根据FieldElement2625x4与vector ( a , b , c , d ) (a,b,c,d) (a,b,c,d)之间的相互转换需借助unpack_pair函数和repack_pair函数:

/// Unpack 32-bit lanes into 64-bit lanes:
/// ```ascii,no_run
/// (a0, b0, a1, b1, c0, d0, c1, d1)
/// ```
/// into
/// ```ascii,no_run
/// (a0, 0, b0, 0, c0, 0, d0, 0)
/// (a1, 0, b1, 0, c1, 0, d1, 0)
/// ```
#[inline(always)]
fn unpack_pair(src: u32x8) -> (u32x8, u32x8) {let a: u32x8;let b: u32x8;let zero = i32x8::new(0, 0, 0, 0, 0, 0, 0, 0);unsafe {use core::arch::x86_64::_mm256_unpackhi_epi32;use core::arch::x86_64::_mm256_unpacklo_epi32;a = _mm256_unpacklo_epi32(src.into_bits(), zero.into_bits()).into_bits();b = _mm256_unpackhi_epi32(src.into_bits(), zero.into_bits()).into_bits();}(a, b)
}
/// Repack 64-bit lanes into 32-bit lanes:
/// ```ascii,no_run
/// (a0, 0, b0, 0, c0, 0, d0, 0)
/// (a1, 0, b1, 0, c1, 0, d1, 0)
/// ```
/// into
/// ```ascii,no_run
/// (a0, b0, a1, b1, c0, d0, c1, d1)
/// ```
#[inline(always)]
fn repack_pair(x: u32x8, y: u32x8) -> u32x8 {unsafe {use core::arch::x86_64::_mm256_blend_epi32;use core::arch::x86_64::_mm256_shuffle_epi32;// Input: x = (a0, 0, b0, 0, c0, 0, d0, 0)// Input: y = (a1, 0, b1, 0, c1, 0, d1, 0)let x_shuffled = _mm256_shuffle_epi32(x.into_bits(), 0b11_01_10_00);let y_shuffled = _mm256_shuffle_epi32(y.into_bits(), 0b10_00_11_01);// x' = (a0, b0,  0,  0, c0, d0,  0,  0)// y' = ( 0,  0, a1, b1,  0,  0, c1, d1)return _mm256_blend_epi32(x_shuffled, y_shuffled, 0b11001100).into_bits();}
}

3. 对于Extend twisted坐标系表示的点 ( X 1 , Y 1 , Z 1 , T 1 ) (X_1,Y_1,Z_1,T_1) (X1,Y1,Z1,T1)的double/add运算

根据论文《Twisted Edwards Curves Revisited》中有相应的串行和并行运算算法:
在这里插入图片描述
在这里插入图片描述

3.1 对于Extend twisted坐标系表示的点 ( X 1 , Y 1 , Z 1 , T 1 ) (X_1,Y_1,Z_1,T_1) (X1,Y1,Z1,T1)的double运算

double算法与实际代码实现中的映射关系为:
R 6 = R 2 + R 3 = S 1 + S 2 = S 5 R_6=R_2+R_3=S_1+S_2=S_5 R6=R2+R3=S1+S2=S5
R 7 = R 2 − R 3 = S 1 − S 2 = S 6 R_7=R_2-R_3=S_1-S_2=S_6 R7=R2R3=S1S2=S6
R 1 = R 4 + R 7 = 2 S 3 + S 1 − S 2 = S 8 R_1=R_4+R_7=2S_3+S_1-S_2=S_8 R1=R4+R7=2S3+S1S2=S8
R 2 = R 6 − R 5 = S 1 + S 2 − S 4 = S 9 R_2=R_6-R_5=S_1+S_2-S_4=S_9 R2=R6R5=S1+S2S4=S9
对应地有:
( S 9 , 0 , S 6 , 0 , S 6 , 0 , S 9 , 0 ) v p m u l u d q ( S 8 , 0 , S 5 , 0 , S 8 , 0 , S 5 , 0 ) = ( S 8 ∗ S 9 , S 6 ∗ S 5 , S 6 ∗ S 8 , S 9 ∗ S 5 ) = ( X 3 , Y 3 , Z 3 , T 3 ) (S_9,0,S_6,0,S_6,0,S_9,0)\ vpmuludq\ (S_8,0,S_5,0,S_8,0,S_5,0)=(S_8*S_9,S_6*S_5,S_6*S_8,S_9*S_5)=(X_3,Y_3,Z_3,T_3) (S9,0,S6,0,S6,0,S9,0) vpmuludq (S8,0,S5,0,S8,0,S5,0)=(S8S9,S6S5,S6S8,S9S5)=(X3,Y3,Z3,T3)

根据博客curve25519-dalek中field reduce原理分析可知,radix为25.5时有: ∵ 2 255 ∗ x 10 ≡ 19 m o d ( 2 255 − 19 ) , w h e n x = 1. \because 2^{255}*x^{10} \equiv 19 \quad mod \quad (2^{255}-19), when\ x=1. 2255x1019mod(225519)when x=1.
以及博客Curve25519 Field域2^255-19内的快速运算,以radix-25.5为例,符合avx2并行计算的设计。对于一个FieldElement,可表示为:
f = f 0 + f 1 2 26 x + f 2 2 51 x 2 + f 3 2 77 x 3 + f 4 2 102 x 4 + f 5 2 128 x 5 + f 6 2 153 x 6 + f 7 2 179 x 7 + f 8 2 204 x 8 + f 9 2 230 x 9 f=f_0+f_12^{26}x+f_22^{51}x^2+f_32^{77}x^3+f_42^{102}x^4+f_52^{128}x^5+f_62^{153}x^6+f_72^{179}x^7+f_82^{204}x^8+f_92^{230}x^9 f=f0+f1226x+f2251x2+f3277x3+f42102x4+f52128x5+f62153x6+f72179x7+f82204x8+f92230x9
g = g 0 + g 1 2 26 x + g 2 2 51 x 2 + g 3 2 77 x 3 + g 4 2 102 x 4 + g 5 2 128 x 5 + g 6 2 153 x 6 + g 7 2 179 x 7 + g 8 2 204 x 8 + g 9 2 230 x 9 g=g_0+g_12^{26}x+g_22^{51}x^2+g_32^{77}x^3+g_42^{102}x^4+g_52^{128}x^5+g_62^{153}x^6+g_72^{179}x^7+g_82^{204}x^8+g_92^{230}x^9 g=g0+g1226x+g2251x2+g3277x3+g42102x4+g52128x5+g62153x6+g72179x7+g82204x8+g92230x9
根据论文《Sandy2x: New Curve25519 Speed Records》有:
在这里插入图片描述

3.2 对于Extend twisted坐标系表示的点 ( X 1 , Y 1 , Z 1 , T 1 ) , ( X 2 , Y 2 , Z 2 , T 2 ) (X_1,Y_1,Z_1,T_1),(X_2,Y_2,Z_2,T_2) (X1,Y1,Z1,T1),(X2,Y2,Z2,T2)的add运算

论文《Twisted Edwards Curves Revisited》并行运算算法设计运行在不同的处理器上,实际软件实现并不可行,因为不同处理器之间的同步效率导致的延时不可接受。(The reason may be that HWCD08 describe their formulas as operating on four independent processors, which would make a software implementation impractical: all of the operations are too low-latency to effectively synchronize.)
在这里插入图片描述
https://doc-internal.dalek.rs/curve25519_dalek/backend/vector/index.html中对以上算法进行了进一步梳理:
在这里插入图片描述
其中的MS分别表示乘法和平方运算,D表示与曲线系数的乘法运算,如上图的 k = 2 d k=2d k=2d。对于Curve25519的曲线表示为: − x 2 + y 2 = 1 + d x 2 y 2 , d = − ( 121665 / 121666 ) , q = 2 255 − 19 -x^2+y^2=1+dx^2y^2, d=-(121665/121666),q=2^{255}-19 x2+y2=1+dx2y2,d=(121665/121666),q=225519
其中的MS具有很好的一致性,适于扩展至vector并行计算。
k = 2 d k=2d k=2d也可转换为以4个元素的vector表示: k = 2 d = k 0 + 2 n k 1 + 2 2 n k 2 + 2 3 n k 3 k=2d=k_0+2^nk_1+2^{2n}k_2+2^{3n}k_3 k=2d=k0+2nk1+22nk2+23nk3,这样就可以直接并行计算 k i ∗ R 7 k_i*R_7 kiR7
d = d 1 d 2 = − 121665 121666 d=\frac{d_1}{d_2}=\frac{-121665}{121666} d=d2d1=121666121665时,以下坐标表示等价:
( R 5 , R 6 , 2 d 1 d 2 R 7 , 2 R 8 ) ← ( d 2 R 5 , d 2 R 6 , 2 d 1 R 7 , 2 d 2 R 8 ) (R_5,R_6,2\frac{d_1}{d_2}R_7,2R_8)\leftarrow(d_2R_5,d_2R_6,2d_1R_7,2d_2R_8) (R5,R6,2d2d1R7,2R8)(d2R5,d2R6,2d1R7,2d2R8)

由此可知,上述的D运算也可转换为与 ( 121666 , 121666 , 2 ∗ 121665 , 2 ∗ 121666 ) (121666,121666,2*121665,2*121666) (121666,121666,2121665,2121666)(注意其中的 2 ∗ 121666 &lt; 2 18 2*121666&lt;2^{18} 2121666<218,其中的每个元素都可存储在32-bit空间内)的并行运算。

在这里插入图片描述

参考资料:
[1] https://doc-internal.dalek.rs/curve25519_dalek/backend/vector/avx2/index.html
[2] CPU指令集——AVX2
[3] Extended twisted Edwards curve坐标系及相互转换
[4] curve25519-dalek中field reduce原理分析
[5] Curve25519 Field域2^255-19内的快速运算
[6] https://doc-internal.dalek.rs/curve25519_dalek/backend/vector/index.html

这篇关于dalek-Curve25519 avx2并行计算学习笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/276102

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件