精华内容
下载资源
问答
  • SIMD

    千次阅读 2021-04-10 09:41:20
    初始SIMD前言AVX基础介绍矩阵乘加速总结 前言 完成了计算机系统原理之后来做一个总结,本次实验时继多线程之后继续研究矩阵乘优化的内容,主要使用SIMD指令集并与上次实验的多线程进行对比。 SIMD即单指令集多数据...

    前言

    完成了计算机系统原理之后来做一个总结,本次实验时继多线程之后继续研究矩阵乘优化的内容,主要使用SIMD指令集并与上次实验的多线程进行对比。

    SIMD即单指令集多数据(Single Instruction Multiple Data)。说的简单一点就是一种向量运算,想象一下在单指令单数据上你要做一个op需要几步?你得先取指译码,然后访问内存获得操作数,然后才能进行计算吧,Intel告诉我们可以用SIMD一下子完成128bit,或者256bit,甚至是512bit数据的运算,怎么理解这样的一个数据结构呢,可以把它想象成一个可以同时按位计算的数组,既然是个数组说明也可以通过索引访问数据,这里有个误区是这个数据结构本身表现出来的数没有太多意义,如一个__m128 a存放了4个float类型的数,那么a就是一个类似数组的东西。

    AVX基础介绍

    MMX和SSE用的不多这里就以AVX为例了如果想看完整的更深层的建议看Intel官网https://software.intel.com/content/www/us/en/develop/home.html

    数据类型

    数据类型描述
    __m128包含四个float类型数字的向量
    __m128d包含两个double类型数字的向量
    __m128i包含若干个int类型数字的向量
    __m256包含八个float类型数字的向量
    __m256d包含四个double类型数字的向量
    __m256i包含若干个int类型数字的向量

    访存操作

    数据类型描述
    _mm256_load_ps/pd从对齐的内存地址加载浮点向量
    _mm256_load_si256从对齐的内存地址加载整形向量
    _mm256_loadu_ps/pd从未对齐的内存地址加载浮点向量
    _mm256_loadu_si256从未对齐的内存地址加载整形向量

    写入的操作把load换成store即可,这里需要知道SIMD是要求对齐的,可以用align对齐,当然你也可以用上述的不对齐时的操作写代码,但是据我测试似乎时间花费更多。

    加减乘

    数据类型描述
    _mm256_add_ps/pd对两个浮点向量做加法
    _mm256_sub_ps/pd对两个浮点向量做减法
    _mm256_mul_ps/pd对两个浮点向量做乘法
    _mm256_hadd_ps/pd水平方向对两个浮点向量做加法
    _mm256_hsud_ps/pd垂直方向对两个浮点向量做加法

    这里解释一下水平方向时怎么操作的,如下图。
    在这里插入图片描述

    矩阵乘加速

    没错又是我们的老朋友矩阵乘,有了上述的基础知识已经完全可以写出一个入门级的SIMD优化代码了。

    int main() {
    	double* A, * B, * C;
    	A = new double[M * N];
    	B = new double[N * P];
    	C = new double[M * P];
    	for (int i = 0; i < M; i++) {
    		for (int j = 0; j < N; j++) {
    		A[i * N + j] = i * N + j;
    		}
    	}
    	for (int i = 0; i < N; i++) {
    		for (int j = 0; j < P; j++) {
    		B[i * P + j] = i * P + j;
    		}
    	}
    avxmul(A, B, C); //avx+转置
    return 0;
    }
    
    //avx+转置
    void avxmul(double* A, double* B, double* C) {
    	for (int i = 0; i < M; i++) {
    	int c = i * P;
    		for (int j = 0; j < P; j++) {
    		C[c + j] = 0;
    		}
    	}
    	clock_t start, end;
    	int i, j, k;
    	double temp;
    	start = clock();
    	double* B1 = T(B);
    	for (i = 0; i < M; i++) {
    		for (j = 0; j < P; j++) {
    		temp = 0; double t[4] = { 0 };
    		int a = i * N; int b = j * N;
    			for (k = 0; k < N && k + 4 <= N; k += 4) {
    			_mm256_store_pd(&t[0],
    			_mm256_mul_pd(_mm256_load_pd(&A[a + k]), _mm256_load_pd(&B1[b + k])));
    			temp += t[0] + t[1] + t[2] + t[3];
    			}
    			C[i * P + j] = temp;
    		}
    	}
    end = clock();
    cout << "avx+转置时间: " << (double)(end - start) / CLOCKS_PER_SEC
    * 1000 << "ms" << endl;
    }
    

    总结

    本次实验我们以 SIMD(单指令多数据)为主要研究对象,实现了矢量加和矩阵乘的优化。在实验过程中我们不断在探讨 SIMD 与 SIMT(单指令多线程)计算机系统-SIMD 程序设计与性能分析之间的区别与联系。

    从单个线程看,假设我们用 SSE 正在处理一个四维向量(指令向量化处理是 SIMD 的核心),这条指令最快在一个 cycle 就能完成,但是在SIMT 架构中则需要把这个四维向量分解开,一个 cycle 处理一个数据,最快也需要 4 个 cycle,但这也需要比起 SIMT 四倍的逻辑单元。换而言之在同等算力进行对比下,其实 SIMD 可以拿出更少的线程个数来实现 SIMT 的算力,这也是为什么在我们的实验中 SIMD 往往优化程度更好的原因。

    但是当我们增加线程数的时候,SIMD 的优势将会逐渐减少,而倘若 SIMD 单纯把向量维度扩大时,浪费也会增加,所以现在一些架构会对 16 个线程分成四组的 SIMD 解决这个问题,当然不管是 SIMD 还是 SIMT 都存在不少的局限,SIMD 需要严格按照维数的整数倍去实现,否则会造成逻辑单元的浪费,而 SIMT 则需要在计算机的可以使用的逻辑单元数内实现线程数的创建,否则线程数的增加将不能导致速度加快,反而需要大量的分支跳转影响了效率,这里也体现了算法设计上面的折衷思想,这种折衷既与算法本身有关,又与对应的硬件有关。

    经过上面的陈述仿佛 SIMD 和SIMT 存在不同程度的对立,但是这并不意味着 SIMD 就不能与 SIMT 进行“合作优化”,我们设计了同时使用 SIMD 与 SIMT 的算法,算法思路也很简单,只需要思考在多线程下每个线程是否支持 SIMD 即可。

    展开全文
  • 通用模拟 generic-simd提供了安全且惯用的零成本抽象,用于编写显式的跨平台SIMD操作。 执照 generic-simd是根据MIT许可证和Apache许可证(2.0版)的条款发行的。 有关详细信息,请参见和 。
  • SIMD测试 结果:启用-O3时,gcc和clang都可以执行简单的SIMD优化。 没有探索更困难的SIMD优化问题。 test-gcc-debug sum: 99897982687.000000 time: 0.446810 test-gcc-o3 sum: 99897982687.000000 time: 0.157358 ...
  • SIMD-源码

    2021-03-28 18:50:42
    简洁示例的SIMD编码
  • SIMD type

    2020-12-09 05:46:09
    <div><p>This PR includes modification for SIMD type. What we want is a single SIMD type implementation that are currently used in a similar way for Sierra, Stokhos and KokkosKernels. <p>Task 1: ...
  • 高效便携式SIMD包装器 该库在现有的特定于平台的内部函数上提供类型安全和源代码可移植包装器。 其设计旨在简化,提高效率并立即使用当前编译器。 当前状态 为标量/ SSE4 / AVX2 / ARMv8目标实现,每个目标都有单元...
  • SIMD初学

    2019-11-28 22:06:03
    SIMD初学 在学习SIMD之前,我们首先需要了解什么是标量与矢量。 浮点运算指令分为两大类:Packed(矢量) 和Scalar(标量)。 Packed指令是一次对寄存器中的四个浮点数(即DATA0 ~ DATA3)均进行计算,而Scalar一...

    SIMD初学

    在学习SIMD之前,我们首先需要了解两个概念。
    浮点运算指令分为两大类:Packed(矢量) 和Scalar(标量)。
    Packed指令是一次对寄存器中的四个浮点数(即DATA0 ~ DATA3)均进行计算,而Scalar一次则只对寄存器中的DATA0进行计算。如下图所示:
    在这里插入图片描述

    1.SIMD的历史与指令集分类

    SIMD(Single Instruction Multiple Data)即单指令流多数据流,是一种采用一个控制器来控制多个处理器,同时对一组数据(又称“数据向量”)中的每一个分别执行相同的操作从而实现空间上的并行性的技术。简单来说就是一个指令能够同时处理多个数据。
    SIMD于20世纪70年代首次引用于ILLIAC IV大规模并行计算机上。而大规模应用到消费级计算机则是在20实际90年代末。

    1996年Intel推出了X86的MMX(MultiMedia eXtension)指令集扩展,MMX定义了8个寄存器,称为MM0到MM7,以及对这些寄存器进行操作的指令。每个寄存器为64位宽,可用于以“压缩”格式保存64位整数或多个较小整数,然后可以将单个指令一次应用于两个32位整数,四个16位整数或8个8位整数。

    intel在1999年又推出了全面覆盖MMX的SSE(Streaming SIMD Extensions, 流式SIMD扩展)指令集,并将其应用到Pentium III系列处理器上,SSE添加了八个新的128位寄存器(XMM0至XMM7),而后来的X86-64扩展又在原来的基础上添加了8个寄存器(XMM8至XMM15)。SSE支持单个寄存器存储4个32位单精度浮点数,之后的SSE2则支持单个寄存器存储2个64位双精度浮点数,2个64位整数或4个32位整数或8个16位短整形。SSE2之后还有SSE3,SSE4以及AVX,AVX2等扩展指令集。

    AVX引入了16个256位寄存器(YMM0至YMM15),AVX的256位寄存器和SSE的128位寄存器存在着相互重叠的关系(XMM寄存器为YMM寄存器的低位),所以最好不要混用AVX与SSE指令集,否在会导致transition penalty(过渡处罚)。

    这里主要讲AVX和SSE这两种指令集。
    AVX与SSE支持的数据类型如下:
    在这里插入图片描述

    2.如何使用SIMD

    使用SIMD总共有下面五种方法,但是这里主要学习使用**内置函数(intrinsics)**的方法。
    1.最简单的方法是使用Intel开发的跨平台函数库(IPP,Intel Integrated Performance Primitives ),里面的函数实现都使用了SIMD指令进行优化。
    2.借助于Auto-vectorization(自动矢量化),借助编译器将标量操作转化为矢量操作。
    3.使用编译器指示符(compiler directive),如Cilk里的#pragma simd和OpenMP里的#pragma omp simd。

    void add_floats(float * a,float * b,float * c,float * d,float * e,int n)
    {
        int i;
    #pragma simd
        for(i = 0; i <n; i ++{
            a [i] = a [i] + b [i] + c [i] + d [i] + e [i];
        }
    }
    

    4.使用内置函数(intrinsics)的方式,如下所示,使用SSE _mm_add_ps 内置函数,一次执行8个单精度浮点数的加法:

    int  main()
    {
    	__m128 v0 = _mm_set_ps(1.0f, 2.0f, 3.0f, 4.0f);
    	__m128 v1 = _mm_set_ps(1.0f, 2.0f, 3.0f, 4.0f);
    
    	__m128 result = _mm_add_ps(v0, v1);
    }
    

    5.是使用汇编直接操作寄存器,直接使用汇编又难又麻烦。

    3.SSE/AVX Intrinsics简介

    1.头文件
    SSE/AVX指令主要定义于以下一些头文件中:
    <xmmintrin.h> : SSE, 支持同时对4个32位单精度浮点数的操作。
    <emmintrin.h> : SSE 2, 支持同时对2个64位双精度浮点数的操作。
    <pmmintrin.h> : SSE 3, 支持对SIMD寄存器的水平操作(horizontal operation),如hadd, hsub等…。
    <tmmintrin.h> : SSSE 3, 增加了额外的instructions。
    <smmintrin.h> : SSE 4.1, 支持点乘以及更多的整形操作。
    <nmmintrin.h> : SSE 4.2, 增加了额外的instructions。(这个支持之前所有版本的SEE)
    <immintrin.h> : AVX, 支持同时操作8个单精度浮点数或4个双精度浮点数。

    2.命名规则(很重要)
    SSE/AVX提供的数据类型和函数的命名规则如下:
    a.数据类型通常以_mxxx(T)的方式进行命名,其中xxx代表数据的位数,如SSE提供的__m128为128位,AVX提供的__m256为256位。T为类型,若为单精度浮点型则省略,若为整形则为i,如__m128i,若为双精度浮点型则为d,如__m256d。
    b.操作浮点数的内置函数命名方式为:_mm(xxx)_name_PT。 xxx为SIMD寄存器的位数,若为128m则省略,如_mm_addsub_ps,若为_256m则为256,如_mm256_add_ps。 name为函数执行的操作的名字,如加法为_mm_add_ps,减法为_mm_sub_ps。 P代表的是对矢量(packed data vector)还是对标量(scalar)进行操作,如_mm_add_ss是只对最低位的32位浮点数执行加法,而_mm_add_ps则是对4个32位浮点数执行加法操作。 T代表浮点数的类型,若为s则为单精度浮点型,若为d则为双精度浮点,如_mm_add_pd和_mm_add_ps。
    c.操作整形的内置函数命名方式为:_mm(xxx)_name_epUY。xxx为SIMD寄存器的位数,若为128位则省略。 name为函数的名字。U为整数的类型,若为无符号类型则为u,否在为i,如_mm_adds_epu16和_mm_adds_epi16。Y为操作的数据类型的位数,如_mm_cvtpd_pi32。

    3.内置函数(instructions)
    1).存取操作(load/store/set)

        __attribute__((aligned(32))) int d1[8] = {-1,-2,-3,-4,-5,-6,-7,-8};
        __m256i d = _mm256_load_si256((__m256i*)d1);//装在int可以使用指针类型转换 必须32位对齐
    
    这里说明一下,使用load函数要保证数组的起始地址32位字节对齐。在linux下就需要__attribute__((aligned(32))),Windows下要用__declspec(align(32))
    

    这里有没有疑问,为什么要字节对齐呢?
    现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
    对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。显然在读取效率上下降很多。

    上面是从手册查询到的load系列的函数。其中,
    _mm_load_ss用于scalar的加载,所以,加载一个单精度浮点数到暂存器的低字节,其它三个字节清0,(r0 := *p, r1 := r2 := r3 := 0.0)。
    _mm_load_ps用于packed的加载(下面的都是用于packed的),要求p的地址是16字节对齐,否则读取的结果会出错,(r0 := p[0], r1 := p[1], r2 := p[2], r3 := p[3])。
    _mm_load1_ps表示将p地址的值,加载到暂存器的四个字节,需要多条指令完成,所以,从性能考虑,在内层循环不要使用这类指令。(r0 := r1 := r2 := r3 := *p)。
    _mm_loadh_pi和_mm_loadl_pi分别用于从两个参数高底字节等组合加载。具体参考手册。
    _mm_loadr_ps表示以_mm_load_ps反向的顺序加载,需要多条指令完成,当然,也要求地址是16字节对齐。(r0 := p[3], r1 := p[2], r2 := p[1], r3 := p[0])。
    _mm_loadu_ps和_mm_load_ps一样的加载,但是不要求地址是16字节对齐,对应指令为movups。

    store系列可以将SSE/AVX提供的类型中的数据存储到内存中,如:

    void test() 
    {
    	__declspec(align(16)) float p[] = { 1.0f, 2.0f, 3.0f, 4.0f };
    	__m128 v = _mm_load_ps(p);
    
    	__declspec(align(16)) float a[] = { 1.0f, 2.0f, 3.0f, 4.0f };
    	_mm_store_ps(a, v);
    }
    

    _mm_store_ps可以__m128中的数据存储到16字节对齐的内存。
    _mm_storeu_ps不要求存储的内存对齐。
    _mm_store_ps1则是把__m128中最低位的浮点数存储为4个相同的连续的浮点数,即:p[0] = m[0], p[1] = m[0], p[2] = m[0], p[3] = m[0]。
    _mm_store_ss是存储__m128中最低位的位浮点数到内存中。
    _mm_storer_ps是按相反顺序存储__m128中的4个浮点数。

    set系列可以直接设置SSE/AVX提供的类型中的数据,如:

    __m128 v = _mm_set_ps(0.5f, 0.2f, 0.3f, 0.4f);
    

    _mm_set_ps可以将4个32位浮点数按相反顺序赋值给__m128中的4个浮点数,即:_mm_set_ps(a, b, c, d) : m[0] = d, m[1] = c, m[2] = b, m[3] = a。
    _mm_set_ps1则是将一个浮点数赋值给__m128中的四个浮点数。
    _mm_set_ss是将给定的浮点数设置到__m128中的最低位浮点数中,并将高三位的浮点数设置为0.
    _mm_setzero_ps是将__m128中的四个浮点数全部设置为0.

    2). 算术运算
    SSE/AVX提供的算术运算操作包括:
    _mm_add_ps,_mm_add_ss 等加法系列
    _mm_sub_ps,_mm_sub_pd 等减法系列
    _mm_mul_ps,_mm_mul_epi32 等乘法系列
    _mm_div_ps,_mm_div_ss 等除法系列
    _mm_sqrt_pd,_mm_rsqrt_ps 等开平方系列
    _mm_rcp_ps,_mm_rcp_ss 等求倒数系列
    _mm_dp_pd,_mm_dp_ps 计算点乘
    此外还有向下取整,向上取整等运算,这里只列出了浮点数支持的算术运算类型,还有一些整形的算术运算类型未列出。

    3).比较运算
    SSE/AVX提供的比较运算操作包括:
    _mm_max_ps逐分量对比两个数据,并将较大的分量存储到返回类型的对应位置中。
    _mm_min_ps逐分量对比两个数据,并将较小的分量存储到返回类型的对应位置中。
    _mm_cmpeq_ps逐分量对比两个数据是否相等。
    _mm_cmpge_ps逐分量对比一个数据是否大于等于另一个是否相等。
    _mm_cmpgt_ps逐分量对比一个数据是否大于另一个是否相等。
    _mm_cmple_ps逐分量对比一个数据是否小于等于另一个是否相等。
    _mm_cmplt_ps逐分量对比一个数据是否小于另一个是否相等。
    _mm_cmpneq_ps逐分量对比一个数据是否不等于另一个是否相等。
    _mm_cmpnge_ps逐分量对比一个数据是否不大于等于另一个是否相等。
    _mm_cmpngt_ps逐分量对比一个数据是否不大于另一个是否相等。
    _mm_cmpnle_ps逐分量对比一个数据是否不小于等于另一个是否相等。
    _mm_cmpnlt_ps逐分量对比一个数据是否不小于另一个是否相等。

    4).逻辑运算
    SSE/AVX提供的逻辑运算操作包括:
    _mm_and_pd对两个数据逐分量and
    _mm_andnot_ps先对第一个数进行not,然后再对两个数据进行逐分量and
    _mm_or_pd对两个数据逐分量or
    _mm_xor_ps对两个数据逐分量xor

    详情可查Intel的Intrinsics Guide

    展开全文
  • simd ES7(建议)SIMD数字类型填充/填充 128位SIMD数值类型ECMAScript稻草人建议。 来源: 该README文件的几乎所有单词以及代码和测试直接来自 。 这样做的目的是使它成为使用的模块,该模块不会自动修改全局环境...
  • SIMD指令大全

    2018-10-16 16:32:43
    Intel 关于SIMD的详细文档,适用于函数的优化,特别是和视频编解码相关
  • WebAssembly SIMD 示例 本示例通过 WebAssembly 演示了 JavaScript 中 SIMD 的用法。 它运行了 2 个大小为 10000 的数组相加的 100000 倍(有关更多详细信息,请参阅 )。 第一个实现是通过 JavaScript 中的一个...
  • simd 该库为GHC 7.8中提供的SIMD primop提供了一个简单的接口。 SIMD(单指令多数据)CPU指令提供了一种并行化数值计算的简便方法。 GHC 7.8提供了primops,使我们可以访问这些CPU指令。 该软件包将primo封装为更加...
  • SIMD Tutorial.pdf

    2021-05-16 21:17:35
    SIMD开发指南
  • SIMD groundwork

    2021-01-08 20:59:13
    <div><p><a href="https://github.com/rust-lang/rfcs/blob/master/text/1199-simd-infrastructure.md">Rendered</a>.</p><p>该提问来源于开源项目:rust-lang/rfcs</p></div>
  • SIMD Julia 中的显式 SIMD 矢量化 Julia CI v1 每晚 概述 这个包允许程序员显式地对他们的 Julia 代码进行 SIMD 向量化。 理想情况下,编译器(Julia 和 LLVM)能够自动执行此操作,尤其是对于直接编写的代码。 ...
  • SIMD-FECFUN 利用SIMD加速与FEC相关的功能
  • SIMD 介绍

    2021-10-18 15:55:04
    AVX是在之前的128bit扩展到和256bit的SIMD(Single Instruction, Multiple Data)。而Sandy Bridge的SIMD演算单元扩展到256bits的同时数据传输也获得了提升,所以从理论上看CPU内核浮点运算性能提升到了2倍。 Intel ...
    • AVX指令集是Sandy Bridge和Larrabee架构下的新指令集。AVX是在之前的128bit扩展到和256bit的SIMD(Single Instruction, Multiple Data)。而Sandy Bridge的SIMD演算单元扩展到256bits的同时数据传输也获得了提升,所以从理论上看CPU内核浮点运算性能提升到了 倍。
    • Intel AVX指令集,在SIMD计算性能增强的同时也沿用了的MMX/SSE指令集。不过 MMX/SSE的不同点在于增强的AVX指令,从指令的格式上就发生了很大的变化。x86(IA32/Intel64)架构的基础上增加了prefix(Prefix),所以实现了新的命令,也使更加复杂指令得以实现,从而提升了x86 CPU的性能。

    SIMD (Single Instruction Multiple Data) 即单条指令操作多条数据——原理即在CPU 寄存器层面实现数据的并行操作。

    LLVM

    LLVM是构架编译器(compiler)的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time),对开发者保持开放,并兼容已有脚本。

    向量化计算vectorization

    向量化计算(vectorization),也叫vectorized operation,也叫array programming,说的是一个事情:将多次for循环计算变成一次计算。

    在这里插入图片描述
    上图中,右侧为vectorization,左侧为经典的标量计算。将多次for循环计算变成一次计算完全仰仗于CPU的SIMD指令集,SIMD指令可以在一条cpu指令上处理2、4、8或者更多份的数据。在Intel处理器上,这个称之为SSE以及后来的AVX;在ARM处理器上,这个称之为NEON。

    因此简单来说,向量化计算就是将一个loop——处理一个array的时候每次处理1个数据共处理N次,转化为vectorization——处理一个array的时候每次同时处理8个数据共处理N/8次。

    当然。
    首先向量化执行引擎效率的发挥需要数据库能够提供列存表的支持。 对于传统的行存表来说,谈向量化执行是不可能的。通常向量化执行引擎都是用在OLAP数仓类系统,因为通常分析型系统通常都是数据处理密集型负载,基本上都是采用顺序方式来访问表中大部分的数据,然后进行计算,最后将计算结果输出给终端用户。对于典型的OLTP点查询,这种类型的查询执行,使用行存表反而比列存表更好。

    每列的数据存储在一起,可以认为这些数据是以数组的方式存储的,基于这样的特征,当该列数据需要进行某一同样操作,可以使用SIMD进一步提升计算效率,即便运算的机器上不支持SIMD, 也可以通过一个循环来高效完成对这个数据块各个值的计算。

    展开全文
  • simd-adler32 SIMD加速的Adler-32滚动哈希算法实现。 特征 没有依赖关系 支持no_std (具有default-features = false ) 运行时CPU功能检测(启用std ) 在尽可能多的目标(目前仅x86和x86_64)上实现快速性能 当...
  • 在 x86 上公开 SIMD 内在函数
  • 便携式SIMD项目组 欢迎使用可移植SIMD项目组的资源库! 这是我们用来组织工作的存储库。 有关我们的目标和当前范围的更多信息,请参考我们的。 当前状态 我们目前正在库中进行初始std::simd实现。 我如何参与其中?...
  • SIMD噪声 用于Rust的超快速SIMD噪声库。 欢迎PR! 特征 梯度噪声(Simplex aka Perlin)1D,2D,3D,4D 分形布朗运动,山脊和湍流 蜂窝噪声(aka Voroni)2D,3D SSE2,SSE41和AVX2指令集以及非SIMD后备 AVX2版本...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,635
精华内容 6,654
关键字:

simd