首页 > 其他分享 >CPU上的快速多维矩阵乘法(草稿)

CPU上的快速多维矩阵乘法(草稿)

时间:2024-07-31 19:17:47浏览次数:19  
标签:周期 草稿 BLAS 矩阵 指令 多维 FLOPS CPU

CPU上的快速多维矩阵乘法(草稿) Numpy可以在大约8毫秒内将4核Intel CPU上的两个1024x1024矩阵相乘。考虑到这归结为18 FLOPS/核心/周期,一个周期需要三分之一纳秒,这是非常快的。Numpy使用高度优化的BLAS实现来实现这一点。BLAS是Basic Linear Algebra子程序的缩写。这些库提供快速实现,例如矩阵乘法或点积。它们有时针对一个特定的(系列)CPU进行定制,如英特尔的MKL或苹果的加速CPU。然而,OpenBLAS等非供应商特定的实现也是可用的。使用普通C++重建大致相似的性能有多难? def MMM(A, B)     C = np.zeros((A.n_rows, B.n_columns))     for row in range(A.n_rows):         for col in range(B.n_columns):             for inner in range(A.n_inner):                 C[row, col] = C[row, col] + A[row, inner] * B[inner, col]     return C 这将导致N(=行)*N(=列)*N(=点积)*2(多+加)=2N³FLOP。   在物理机器上运行 在Numpy中,我们示例的代码如下: x = np.random.randn(1024, 1024).astype(np.float32) y = np.random.randn(1024, 1024).astype(np.float32) start = time.time_ns() z = np.dot(x, y) end = time.time_ns() - start 当我在配备英特尔i7-6700(四核Haswell CPU)的专用服务器上运行此程序时,需要8毫秒。 总流量:20亿。 总内存(LOAD):使用fp32时为8MB。 总周期:8ms x 3.4GHz=2700万 在2015年发布的硬件上,这是18个FLOPS/核心/周期,或约250GFLOP/s。太多了! 单个核心如何在一个周期内完成18次浮点运算? 在我的Haswell服务器上,Numpy使用英特尔的BLAS MKL实现。我们特别关心SGEMM函数是如何实现的,这是矩阵乘法所需的函数。SGEMM是单精度通用矩阵倍数的缩写。GEMM执行此计算:C=α*A*B+β*C。A、B、C是矩阵,α、β是标量。在二进制文件中,有多个SGEMM实现,每个实现都特定于英特尔的一种微体系结构:例如SGEMM_kernel_HASWELL、SGEMM_ernel_SANDYBRIDGE…在运行时,BLAS库将使用cpuid指令查询处理器的详细信息,然后调用合适的函数。 仔细查看相关的sgem_kernel_HASWELL,速度来自使用矢量化。矢量化/SMD指令一次对矢量输入的所有条目执行相同的指令:FMAFMA代表融合多加。这意味着执行A=A+B*C,但使用单个(融合)指令。有时这也被称为MAC(乘法累加)。指令,在我的特定情况下是VFMADD指令。它在三个256位长的YMM寄存器上运行,计算(YMM1*YMM2)+YMM3,并将结果存储在YMM3中。这允许CPU在一条指令中执行16个单精度浮点运算。检查Agner Fog的指令表和uops.info,VFMADD有一个吞吐量。令人困惑的是,这是互惠吞吐量,即同一线程中一系列同类独立指令的每条指令的平均时钟周期数。0.5个周期。这意味着我们的理论上限应该是每个周期2个VFMADD指令,或32个FLOPS/周期。 延迟延迟这里是启动指令和使结果可用于其他指令之间的循环数。在5个周期中,这意味着我们需要找到10*16个可以独立调度的FLOPS,因为之前的指令的结果在启动后只有5个周期可用。在编写优化代码时,这将是一个考虑因素:将足够多的独立操作分组,以便CPU可以一次调度所有操作,充分利用其指令级并行性(ILP)功能。 综上所述,英特尔的BLAS库实现了18 FLOPS/核/周期,其中理论上限为32 FLOPS/核心/周期。相当狂野!实际上,实现速度更快,因为我们还测量了一些Python开销和启动OpenMP线程池的时间。 请注意,即使矩阵没有那么大,我们已经很强地计算了界限。从RAM加载8MB可能需要200μs,假设多线程、SIMD内存访问的内存带宽为40GB/s。来自优秀餐巾纸数学项目的数字。。如果矩阵变大,我们的计算量就会变大,因为我们对2n²的负载执行2n³FLOPS。 试图从头开始重现这种表现 为了破坏结果,我们最终将实现一个执行9个FLOPS/core/循环的实现,但仅适用于特定大小的矩阵。本文的目标不是编写一个有竞争力的BLAS实现,而是学习常见的性能优化。相比之下,OpenBlas中的MMM实现是手写汇编的约7K LOC。 我在专用服务器上的3.40GHz四核Intel i7-6700 CPU上运行此程序。它具有每核32KiB的L1d缓存、每核256KiB的L2缓存和共享的8MB L3缓存。用lstopo可视化: 我使用的编译器是clang v14.0。基准测试是通过谷歌基准测试完成的。     添加图片注释,不超过 140 字(可选)

执行 时间
(ms)
初步实施
(RCI)
4481
朴素实现
(RCI) + 编译器标志
1621
初步实施
(RCI) + 标志+寄存器累计
1512
缓存感知循环重新排序
(RIC)
89
循环重新排序
(RIC) + L1 tiling on I
70
循环重排序
(RIC) + I上的L1平铺 + R&C上的多线程
16
Numpy (MKL) 8
      参考文献链接 CPU上的快速多维矩阵乘法

标签:周期,草稿,BLAS,矩阵,指令,多维,FLOPS,CPU
From: https://www.cnblogs.com/wujianming-110117/p/18335280

相关文章

  • yolov8 训练自定义数据集(windows+CPU)
    本文实现使用yolov8训练自己的火灾数据集。1.数据的获取。本文所使用的火灾数据集是在Roboflow上下载的。Roboflow是一款专为YOLOv8设计的自动化训练数据工具,它为YOLOv8提供了一种更便捷、更快速的方式来准备训练数据。它能够自动从开发者提供的原始图像数据中提取所需的信息,并......
  • 当运行程序发生CPU飙升怎么排查问题?
    以下内容由ChatGPT生成当运行Java程序时出现CPU飙升的情况,可能会导致系统性能下降或者应用程序不稳定。排查CPU飙升问题通常需要分几个步骤来进行:1.初步检查监控工具:使用系统监控工具(如Linux上的top或htop,Windows上的任务管理器,或macOS上的活动监视器)来确认是哪个进程占用了......
  • 多维度数组
    多维度数组多维度数组(MultidimensionalArrays)在Java中可以视为数组的数组,最常见的是二维数组,但Java也支持更多维度的数组。多维度数组在内存中并不是连续存储的,它们是按行或按列连续的,这取决于数组的布局方式。声明多维度数组:javaint[][]twoDimArray;//声明一个二维数组i......
  • Intel CPU处理器可扩展平台
    一、Whitley平台第三代Intel可扩展处理器平台Whitley采用IceLake-SP(IceLakeSP:概述和技术文档(intel.cn)),面向2P服务器(2路服务器)。该架构支持每插槽64个PCIeGen4通道,可实现更高的每核I/O带宽,并在8个通道、2DPC(每通道2个DIMM)配置下支持频率高达3200MT/秒的DDR4内存。搭载C......
  • 吴恩达机器学习_第2周_多维特征
    第1周:引言、单变量回归第2周:多维特征第3章多维特征3.1多维特征和向量化3.2多变量梯度下降3.3梯度下降法实践1-特征缩放3.3.1目的3.3.2三种scaling的方式3.4梯度下降法实践2-判断梯度下降是否收敛3.5梯度下降法实践3-学习率......
  • 一维\多维数组
     一、声明数组变量必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:dataType[]arrayRefVar; //首选的方法或dataTypearrayRefVar[]; //效果相同,但不是首选方法注意:建议使用dataType[]arrayRefVar的声明风格声明数组变量。dataTypearrayRefV......
  • 获取 CPU信息,并通过注册表写入
    获取MAC地址输入getmac如下所示: 获取CPUID输入wmiccpugetprocessorid如下所示: 获取产品UUID输入wmiccsproductgetUUID如下所示: 创建reg文件,并输入自己想要修改的内容,具体步骤参考使用注册表文件(REG)添加、修改或删除Windows注册表项和值-最初的幸福ever......
  • yolov8 实现火灾检测(windows+CPU)
    本文实现在windows+CPU的环境下实现实时火宅检测项目网址:https://github.com/noorkhokhar99/Fire-Detection-using-YOLOv8具体实现步骤:1.使用Anaconda搭建一个新的虚拟环境: condacreate-nyolov8_fire_detectionpython==3.92.在GitHub上下载该项目,可以直接点击......
  • cpu 爆满了,怎么处理
    一、问题定位1)缓存命中率过高:缓存命中率过高可能导致大量请求直接落在Redis上,而Redis单线程模型在处理这些请求时可能无法及时响应,从而导致CPU使用率上升。2)高并发写入:在高并发的数据写入场景下,Redis需要频繁处理写入请求,这会导致CPU使用率升高。3)慢查询或高消耗命令:使用了......
  • 操作系统的进程与CPU资源
    1、时间片(TimeSlice):是一种用于多任务处理和进程调度的机制,是分时操作系统分配给每个正在运行的进程微观上的一段CPU时间。2、时间片轮转调度:是操作系统调度策略的一种,其核心思想是每个进程循环的在CPU资源进行执行,微观上每个进程都可以在一定时间片内独占CPU资源进行执行。......