混合精度、异构计算——杂记

news2024/11/21 1:34:55

1、英伟达GPU架构

Figure 1 shows a full GA100 GPU with 128 SMs. The A100 is based on GA100 and has 108 SMs.

SM是streaming multiprocessor的简写,4个处理单元组成一个SM,如Figure 2。

每个SM有64个INT32,64个FP32,32个FP64的CUDA core;每个SM还有4个Tensor Core。SM内共享L1缓存。

CUDA Core是用作通用计算的,Tensor Core是专门针对深度学习优化的,负责矩阵运算、混合精度运算。

Figure 1 GA100 Full GPU with 128 SMs. The A100 Tensor Core GPU has 108 SMs.

Figure 2. The GA100 streaming multiprocessor (SM)

Figure 3展示了NVDIA不同代GPU的特性。

Figure 3. 各代GPU架构

Tensor Core是从2017年的Volta架构开始演变的针对AI模型大量乘加运算的特殊处理单元。

在A100中,Tensor Core3.0能够支持所有的数据类型,包括FP16, BF16, TF32, FP64, INT8, INT4。提供了针对HPC用途的FP64双精度强大算力。

混合精度在底层硬件算子层面,使用半精度(FP16)作为输入和输出,使用全精度(FP32)进行中间结果计算从而不损失过多精度的技术。这个底层硬件层面其实指的就是Tensor  Core,所以GPU上有Tensor Core是使用混合精度训练加速的必要条件。

可以说Tensor Core 是混合精度训练的底层硬件支持

Tensor Core 的基本运算单元为 D = A*B + C,其中A、B、C、D 均为矩阵。每个 Tensor Core 能在一个时钟周期内完成 4*4 的 mma (matrix multiply accumalation) 运算,即一次矩阵乘法和一次矩阵加法。 (D = A*B + C是深度学习中最重要的算子,output = weight * input + bias)

Figure 4. 使用FP16做乘法,使用FP32做加法(避免大数吃小数)

2. MAGMA库

MAGMA的介绍:

MAGMA is intended for CUDA enabled NVIDIA GPUs and HIP enabled AMD GPUs.

It supports NVIDIA's Kepler, Maxwell, Pascal, Volta, Turing, Ampere, and Hopper

GPUs, and AMD's HIP GPUs.

Included are routines for the following algorithms:

    * LU, QR, and Cholesky factorizations

    * Hessenberg, bidiagonal, and tridiagonal reductions

    * Linear solvers based on LU, QR, and Cholesky

    * Eigenvalue and singular value (SVD) problem solvers

    * Generalized Hermitian-definite eigenproblem solver

    * Mixed-precision iterative refinement solvers based on LU, QR, and Cholesky

    * MAGMA BLAS including gemm, gemv, symv, and trsm

    * Batched MAGMA BLAS including gemm, gemv, herk, and trsm

    * Batched MAGMA LAPACK including LU, inverse (getri), QR, and Cholesky factorizations

    * MAGMA Sparse including CG, GMRES, BiCGSTAB, LOBPCG, iterative refinement,

      preconditioners, sparse kernels (SpMV, SpMM), and support for CSR, ELL, and

      SELL-P data formats

MAGMA的Dense Linear Algebra库是有混合精度算法(指Iterative Refinement,在MAGMA 2.5版本发布)。

 比如下面两个接口magma_dsgesv_iteref_gpu和magma_dhgesv_iteref_gpu:

1- The FP32 to FP64 API magma_dsgesv_iteref_gpu, which is similar to the LAPACK dsgesv API. Here A, X, and B are FP64, the routine does the internal conversion and computation, and provides FP64 solution.

2- The FP16 to FP64 API magma_dhgesv_iteref_gpu, which is similar to the magma_dsgesv_gpu API, except it does use the tensor cores and performs computations in FP16. Here A, X, and B are FP64, the routine does the internal conversion and computation, and provides FP64 solution.

MAGMA 是在2018年时发布的MAGMA 2.5,支持了Tensor Core的计算,支持混合精度计算。

 2.5.0 - Nov 16, 2018
    * New routines: Magma is releasing the Nvidia Tensor Cores version
      of its linear mixed-precision solver that is able to provide an
      FP64 solution with up to 4X speedup. The release includes:
      magma_dhgesv_iteref_gpu (FP64-FP16 solver with FP64 input and solution)
      magma_dsgesv_iteref_gpu (FP64-FP32 solver with FP64 input and solution)
      magma_hgetrf_gpu        (mixed precision FP32-FP16 LU factorization)
      magma_htgetrf_gpu       (mixed precision FP32-FP16 LU factorization using Tensor Cores)

3. MAGMA Sparse

MAGMA Sparse支持稀疏线性系统的计算,但是solver的接口没有ds和cz开头的混合精度接口。

MAGMA Sparse中迭代法的算法,比如BICGSTAB,是在原始算法的基础上,做了很多算法重新设计以充分利用GPU的性能,并不是说用了混合精度就达到了这个加速目的。

下面左侧表示了原始BICGSTAB算法,右侧表示把这套算法简单粗暴地掉用CUBLAS算子实现,具体实现。这样做的话,并不能充分利用GPU的性能。需要作一些特殊的处理。

在MAGMA中的BICGSTAB主要做了下面的重设计,该算法称为merged-BICGSTAB:

  1. 将多个算术运算聚合(merge)到单个内核(kernel)中以减少GPU内存运输和CPU-GPU间的通信。
  2. 设计高效的dot kernel,允许多个点积的同时计算

性能对比时,指定双精度计算。得到如下的对比。

MAGMA Sparse是有内置的Iterative Refinement算法的,在magma_diterref、magma_siterref、magma_citerref和magma_ziterref等函数。

下面看一下magma_diterref的源码,可以发现算法实现并不复杂:

/*
    -- MAGMA (version 2.8.0) --
       Univ. of Tennessee, Knoxville
       Univ. of California, Berkeley
       Univ. of Colorado, Denver
       @date March 2024

       @author Hartwig Anzt

       @generated from sparse/src/ziterref.cpp, normal z -> d, Thu Mar 28 12:29:00 2024
*/

#include "magmasparse_internal.h"

#define RTOLERANCE     lapackf77_dlamch( "E" )
#define ATOLERANCE     lapackf77_dlamch( "E" )


/**
    Purpose
    -------

    Solves a system of linear equations
       A * X = B
    where A is a real symmetric N-by-N positive definite matrix A.
    This is a GPU implementation of the Iterative Refinement method.
    The inner solver is passed via the preconditioner argument.

    Arguments
    ---------

    @param[in]
    A           magma_d_matrix
                input matrix A

    @param[in]
    b           magma_d_matrix
                RHS b

    @param[in,out]
    x           magma_d_matrix*
                solution approximation

    @param[in,out]
    solver_par  magma_d_solver_par*
                solver parameters

    @param[in,out]
    precond_par magma_d_preconditioner*
                inner solver
    @param[in]
    queue       magma_queue_t
                Queue to execute in.

    @ingroup magmasparse_dgesv
    ********************************************************************/

extern "C" magma_int_t
magma_diterref(
    magma_d_matrix A, magma_d_matrix b, magma_d_matrix *x,
    magma_d_solver_par *solver_par, magma_d_preconditioner *precond_par,
    magma_queue_t queue )
{
    magma_int_t info = MAGMA_NOTCONVERGED;
    
    // some useful variables
    double c_zero = MAGMA_D_ZERO;
    double c_one  = MAGMA_D_ONE;
    double c_neg_one = MAGMA_D_NEG_ONE;

    // prepare solver feedback
    solver_par->solver = Magma_ITERREF;
    solver_par->numiter = 0;
    solver_par->spmv_count = 0;
    
    magma_int_t dofs = A.num_rows*b.num_cols;

    // solver variables
    double nom, nom0;
    
    // workspace
    magma_d_matrix r={Magma_CSR}, z={Magma_CSR};
    CHECK( magma_dvinit( &r, Magma_DEV, A.num_rows, b.num_cols, c_zero, queue ));
    CHECK( magma_dvinit( &z, Magma_DEV, A.num_rows, b.num_cols, c_zero, queue ));

    double residual;
    CHECK( magma_dresidual( A, b, *x, &residual, queue ));
    solver_par->init_res = residual;
   

    // solver setup
    magma_dscal( dofs, c_zero, x->dval, 1, queue );                    // x = 0
    //CHECK(  magma_dresidualvec( A, b, *x, &r, nom, queue));
    magma_dcopy( dofs, b.dval, 1, r.dval, 1, queue );                    // r = b
    nom0 = magma_dnrm2( dofs, r.dval, 1, queue );                       // nom0 = || r ||
    nom = nom0 * nom0;
    solver_par->init_res = nom0;

    if( nom0 < solver_par->atol ||
        nom0/solver_par->init_res < solver_par->rtol ){
        solver_par->final_res = solver_par->init_res;
        solver_par->iter_res = solver_par->init_res;
        info = MAGMA_SUCCESS;
        goto cleanup;
    }
    
    //Chronometry
    real_Double_t tempo1, tempo2;
    tempo1 = magma_sync_wtime( queue );
    if ( solver_par->verbose > 0 ) {
        solver_par->res_vec[0] = nom0;
        solver_par->timing[0] = 0.0;
    }
    
    // start iteration
    for( solver_par->numiter= 1; solver_par->numiter<solver_par->maxiter;
                                                    solver_par->numiter++ ) {
        magma_dscal( dofs, MAGMA_D_MAKE(1./nom, 0.), r.dval, 1, queue );  // scale it
        CHECK( magma_d_precond( A, r, &z, precond_par, queue )); // inner solver:  A * z = r
        magma_dscal( dofs, MAGMA_D_MAKE(nom, 0.), z.dval, 1, queue );  // scale it
        magma_daxpy( dofs,  c_one, z.dval, 1, x->dval, 1, queue );        // x = x + z
        CHECK( magma_d_spmv( c_neg_one, A, *x, c_zero, r, queue ));      // r = - A x
        solver_par->spmv_count++;
        magma_daxpy( dofs,  c_one, b.dval, 1, r.dval, 1, queue );         // r = r + b
        nom = magma_dnrm2( dofs, r.dval, 1, queue );                    // nom = || r ||

        if ( solver_par->verbose > 0 ) {
            tempo2 = magma_sync_wtime( queue );
            if ( (solver_par->numiter)%solver_par->verbose==0 ) {
                solver_par->res_vec[(solver_par->numiter)/solver_par->verbose]
                        = (real_Double_t) nom;
                solver_par->timing[(solver_par->numiter)/solver_par->verbose]
                        = (real_Double_t) tempo2-tempo1;
            }
        }

        if( nom < solver_par->atol ||
            nom/solver_par->init_res < solver_par->rtol ){
            break;
        }
    }
    tempo2 = magma_sync_wtime( queue );
    solver_par->runtime = (real_Double_t) tempo2-tempo1;
    CHECK(  magma_dresidualvec( A, b, *x, &r, &residual, queue));
    solver_par->final_res = residual;
    solver_par->iter_res = nom;

    if ( solver_par->numiter < solver_par->maxiter ) {
        info = MAGMA_SUCCESS;
    } else if ( solver_par->init_res > solver_par->final_res ) {
        if ( solver_par->verbose > 0 ) {
            if ( (solver_par->numiter)%solver_par->verbose==0 ) {
                solver_par->res_vec[(solver_par->numiter)/solver_par->verbose]
                        = (real_Double_t) nom;
                solver_par->timing[(solver_par->numiter)/solver_par->verbose]
                        = (real_Double_t) tempo2-tempo1;
            }
        }
        info = MAGMA_SLOW_CONVERGENCE;
        if( solver_par->iter_res < solver_par->atol ||
            solver_par->iter_res/solver_par->init_res < solver_par->rtol ){
            info = MAGMA_SUCCESS;
        }
    }
    else {
        if ( solver_par->verbose > 0 ) {
            if ( (solver_par->numiter)%solver_par->verbose==0 ) {
                solver_par->res_vec[(solver_par->numiter)/solver_par->verbose]
                        = (real_Double_t) nom;
                solver_par->timing[(solver_par->numiter)/solver_par->verbose]
                        = (real_Double_t) tempo2-tempo1;
            }
        }
        info = MAGMA_DIVERGENCE;
    }
    
cleanup:
    magma_dmfree(&r, queue );
    magma_dmfree(&z, queue );

    solver_par->info = info;
    return info;
}   /* magma_diterref */

MAGMA Sparse有一些混合精度的算子,详见magma-2.8.0\sparse\include\magmasparse_ds.h文件。

也有混合精度的SpMV的kernel如magma_dsgecsrmv_mixed_prec。

Purpose
    -------
    
    This routine computes y = alpha *  A *  x + beta * y on the GPU.
    A is a matrix in mixed precision, i.e. the diagonal values are stored in
    high precision, the offdiagonal values in low precision.
    The input format is a CSR (val, row, col) in FloatComplex storing all 
    offdiagonal elements and an array containing the diagonal values in 
    DoubleComplex.

magma_dsgecsrmv_mixed_prec(
    magma_trans_t transA,
    magma_int_t m, magma_int_t n,
    double alpha,
    magmaDouble_ptr ddiagval,
    magmaFloat_ptr doffdiagval,
    magmaIndex_ptr drowptr,
    magmaIndex_ptr dcolind,
    magmaDouble_ptr dx,
    double beta,
    magmaDouble_ptr dy,
    magma_queue_t queue )

4. Ginkgo库

Ginkgo是一个高性能的多核系统线性代数库,专注于求解稀疏线性系统。它是使用现代c++实现的(你至少需要一个c++ 14兼容的编译器来构建它),GPU内核在CUDA (NVIDIA设备),HIP (AMD设备)和SYCL/ dpc++ (Intel GPU)以及OpenMP (Intel/AMD/ARM multicore)实现。

Ginkgo的加速主要依赖混合精度算法,有下面三方面:

  1. 将存储精度与算术精度解耦。这能够加速内存绑定(memory-bound)算法的性能,可以补偿或容忍内存操作中的一些信息丢失。
  2. 允许不同精度格式的线性算子和向量之间的组合,而无需显式转换。
  3. 多种混合精度算法,比如SAI预处理、CB-GMRES等。

"Memory-bound algorithm"(内存绑定算法)是指在执行过程中主要受限于内存带宽或内存访问速度的算法。在计算机系统中,处理器(CPU)和内存(RAM)之间的数据传输速度通常是一个瓶颈。当算法的执行时间主要取决于内存访问的速度,而不是计算本身的速度时,就称该算法为内存绑定算法。

参考:

https://developer.nvidia.com/blog/nvidia-ampere-architecture-in-depth/

AI 工程师都应该知道的GPU工作原理,TensorCore_哔哩哔哩_bilibili

 MAGMA的核心算法文献:https://icl.utk.edu/~tomov/MAGMA_Publications.bib

着重看下面的:

Magma Sparse中的BICGSTAB: Hartwig Anzt, 2014, Optimizing Krylov Subspace Solvers on Graphics Processing Units.

利用Tensor Core的mixed-precision iterative refinement solvers:Azzam Haidar, Stanimire Tomov, Jack Dongarra, and Nicholas J. Higham. 2018. Harnessing GPU tensor cores for fast FP16 arithmetic to speed up mixed-precision iterative refinement solvers. 

Ginkgo的文献:Ginkgo: Citing Ginkgo

核心文献如下

总体设计:Ginkgo: A Modern Linear Operator Algebra Framework for High Performance Computing

算法概览:Advances in Mixed Precision Algorithms 2021 Edition

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1978769.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux网络】网络层协议:IP

本篇博客整理了 TCP/IP 分层模型中网络层的 IP 协议&#xff0c;旨在让读者更加深入理解网络协议栈的设计和网络编程。 目录 一、网络层 二、IP 报头 1&#xff09;报头与有效载荷的分离 2&#xff09;有效载荷的上交 3&#xff09;源 IP 与目的 IP 4&#xff09;生存时间…

大模型学习笔记 - 大纲

LLM 大纲 LLM 大纲 1. LLM 模型架构 LLM 技术细节 - 注意力机制LLM 技术细节 - 位置编码 2. LLM 预训练3. LLM 指令微调 LLM 高效微调技术 4. LLM 人类对齐 LLM InstructGPTLLM PPO算法LLM DPO 算法 5. LLM 解码与部署6. LLM 模型LLaMA 系列7. LLM RAG 1. LLM 模型架构 大模…

奥特曼格斗进化0-3汉化版丨奈克瑟斯手机版,PC+安卓合集

今天小孩吵着要玩奈克瑟斯手机游戏&#xff0c;都是平时看那些游戏主播打这些游戏。 看着家里几千张奥特曼卡&#xff0c;脑壳就疼&#xff0c;索性还是闲鱼买了&#xff0c;因为我也没找到很全的。挨个找了个遍就不浪费时间了 百度网盘哈&#xff0c;也懒得转迅雷&#xff0c…

PXE——安装,配置,测试(rhel7环境下)

什么是PXE PXE&#xff08;Preboot eXecution Environment&#xff0c;预启动执行环境&#xff09;允许计算机在开机时从网络而非本地硬盘或其他存储设备启动。这种技术主要用于网络启动和自动化安装系统&#xff0c;尤其在需要为大量计算机同时安装操作系统的情况下非常有用。…

jupyter notebook安装

1.安装 pip install notebook 2.显示配置文件&#xff1a; jupyter notebook --generate-config 3.修改代码路径&#xff1a; 编辑配置文件C:\Users\a\.jupyterjupyter_notebook_config.py 4.运行 jupyter notebook 会自动弹出http://localhost:8888/tree

Elastic:IK分词器分词、停用词热更新如何配置-基于数据库

上一期&#xff0c;我们说明了基于API形式的热更新&#xff0c;但是API形式的热更新存在词库的管理不方便&#xff0c;要直接操作磁盘文件&#xff0c;检索页很麻烦&#xff1b;文件的读写没有专门的优化&#xff0c;性能不好&#xff1b;多一次接口调用和网络传输等缺点&#…

软件测试需要具备的基础知识【功能测试】---前端知识(一)

​ ​ 您好&#xff0c;我是程序员小羊&#xff01; 前言 为了更好的学习软件测试的相关技能&#xff0c;需要具备一定的基础知识。需要学习的基础知识包括&#xff1a; 1、计算机基础 2、前端知识 3、后端知识 4、软件测试理论 后期分四篇文章进行编写&#xff0c;这是第二篇 …

MongoDB未授权访问漏洞

开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作&#xff08;增、删、改、查高危动作&#xff09;而且可以远程访问数据库。 漏洞原因 造成未授权访问的根本原因就在于启动 Mongodb 的时候未设置 --auth 也很少…

Node.js的下一代浏览器和移动自动化测试框架-WebdriverIO

在现代软件开发中&#xff0c;自动化测试已成为保障软件质量的关键环节。而在众多测试框架中&#xff0c;WebdriverIO凭借其强大的功能和简洁的语法&#xff0c;成为Node.js生态中备受瞩目的浏览器和移动自动化测试框架。那么&#xff0c;WebdriverIO究竟有哪些独特之处&#x…

Substance Painter材质制作原理

21 材质制作原理_哔哩哔哩_bilibili 颜色&#xff0c;纹理&#xff0c;高光 木头的制作 玻璃的制作 玻璃要给一定的金属度

指标一致化处理

什么是数据指标 数据指标有别于传统意义上的统计指标&#xff0c;它是通过对数据进行分析得到的一个汇总结果&#xff0c;是将业务单元精分和量化后的度量值&#xff0c;使得业务目标可描述、可度量、可拆解。 数据指标有哪些类型 极大型:期望取值越大越好&#xff1b; 极小…

战略项目与可以帮助战略的项目

在公司内&#xff0c;如果没有机会做战略项目&#xff0c;那么就尽可能让自己的项目产生一些可以被战略项目使用的成果&#xff0c;最好是可以被多个战略项目使用的成果。 或者&#xff0c;将自己的项目和战略项目融合。 比如&#xff0c;一家生产面包的企业&#xff0c;你是负…

用PyTorch 从零开始构建 BitNet 1.58bit

我们手动实现BitNet的编写&#xff0c;并进行的一系列小实验证实&#xff0c;看看1.58bit 模型是否与全精度的大型语言模型相媲美&#xff01; 什么是量化以及为什么需要它&#xff1f; 量化是用更少的比特数表示浮点数的过程。当两个数字使用不同的比特数进行量化时&#xf…

一篇教会你PXE高效批量网络装机及kickstart无人值守安装

目录 搭建PXE的前提 搭建PEX的过程 如何构建PXE服务器 搭建本地yum源 搭建apache 创建软链接将本地yum源到apache页面下 搭建dhcp服务 dhcp配置文件如下 使用system-config-kickstart生成ks.cfg文件 &#xff0c;.cfg配置文件如下 搭建TFTP服务 搭建完成后测试 搭建…

跟李沐学AI:NiN网络中的网络

NiN块 一个卷积层后跟着两个全连接层&#xff08;实际为核窗口大小为1x1的卷积层&#xff09;。卷积层步幅为1&#xff0c;无填充&#xff0c;输出形状与卷积层输出形状相同&#xff0c;起到全连接层的作用。 NiN架构 无全连接层&#xff0c;交替使用NiN块和步幅为2的最大池化…

【C++标准模版库】list的介绍及使用

list 一.list的介绍二.list的使用1.list 构造函数2.list 空间大小3.list 增删查改4.list 迭代器的使用1.正向迭代器2.反向迭代器 5.list 其他成员函数 三.vector与list关于sort性能的比较 一.list的介绍 C中的list标准模板库&#xff08;STL&#xff09;是C标准库中的一个重要组…

Linux文件管理和IO重定向知识总结

目录 一&#xff0c;文件管理 Linux的目录结构是一个树状结构&#xff1a; 文件的分类&#xff1a; 操作文件的常用命令&#xff1a; 文件元数据和节点和inode表结构&#xff1a; 特点&#xff1a; 创建文件&#xff1a; 查看文件inode号&#xff1a; cp和inode&#x…

揭秘Matplotlib等高线图:让数据‘高山流水‘间,笑点与深度并存!

1. 引言 在这个数据如山的时代&#xff0c;你是不是也曾在茫茫数海中迷失方向&#xff0c;渴望找到那片隐藏的“数据绿洲”&#xff1f;别怕&#xff0c;今天咱们就来聊聊Matplotlib这位绘图界的魔术师&#xff0c;特别是它那令人叹为观止的等高线图技能。想象一下&#xff0c…

领域模型(Domain Model)

前言 软件的核心是其为用户解决领域相关的问题的能力。所有其他特性&#xff0c;不管有多么重要&#xff0c;都要服务于这个基本目的。当领域很复杂时&#xff0c;这是一项艰巨的任务&#xff0c;要求高水平技术人员的共同努力。开发人员必须钻研领域以获取业务知识。他们必须…

拉刀基础知识——拉刀的种类

如前面所说&#xff1a;近期要围绕拉削和拉刀这个话题&#xff0c;分享一些相关的内容&#xff0c;从最基础的知识开始&#xff0c;为此还专门买了本旧书——《拉刀设计》入门学习。废话不多说&#xff0c;直接开始。 拉刀最早由冲头演变而来&#xff0c;用于加工方孔&#xf…