论文部分内容阅读
稠密线性代数数学库是科学与工程计算领域最为基础的软件工具,几乎所有科学计算问题都依赖于矩阵计算这一基本计算形式。在稠密线性代数计算软件栈中,最底层最基础的数学库当属BLAS(Basic Linear Algebra Subprograms)程序库。BLAS选取了一组在数值计算程序中被经常使用的矩阵(向量)操作,为它们制定了规范化的编程接口(API),作为构建科学计算软件的基本模块。经过多年的学术研究与生产实践,BLAS的接口规范得到了学术界与工业界的广泛认可,业已成为事实上的标准程序库。通用矩阵乘法例程(GEneral Matrix Multiply)是BLAS库中最重要的计算例程。研究表明,BLAS库中多数Level-3计算例程的计算部分都可以通过调用GEMM例程完成,即,GEMM例程可以作为整个Level-3BLAS的构建基础。因此,优化GEMM例程便成为高性能BLAS库开发工作的重中之重。当前,计算硬件的发展十分迅速。对通用处理器(CPU)而言,其体系结构呈现出多方面发展趋势,包括单指令多数据(SIMD)并行指令扩展在高性能处理器中的广泛应用,单处理器核心数目持续增长,处理器片上存储层次结构不断多样化、复杂化,内存节点增多导致非一致性内存访问(NUMA)效应进一步凸显等。这些新的发展趋势都为高性能BLAS库的开发带来了新的挑战。本论文面向多核与众核通用处理器,对高性能BLAS库的开发优化展开研究。论文的主要工作包括:(1)提出了一种基于编译器的可移植的GEMM kernel函数优化方法Poca。在当前的BLAS库实现中,为了最大限度地开发处理器的指令级并行能力,GEMM例程中执行浮点计算的kernel函数通常由领域专家使用汇编语言编写。每一款处理器芯片都需要领域专家针对其微体系结构特点编写专用的汇编程序,造成该方法耗费人力成本高,程序可移植性差。Poca的核心思路是利用LLVM编译器中对不同处理器微体系结构建立的统一抽象模型,提出一套kernel函数的自动生成与优化过程。该优化过程与具体的处理器平台无关,使得Poca方法具有良好的平台移植性。并且,通过采用与领域专家编写汇编程序相似的优化技术,Poca方法可以达到与专家汇编程序相当甚至更优的程序性能。(2)提出了一种针对非LRU(Least Recently Used)替换策略共享cache的cache划分策略SCP。现有的GEMM实现通常假设处理器核的L1 cache与L2cache皆为私有,并且采用LRU替换策略。但随着处理器体系结构发展,出现了使用非LRU共享cache的高性能处理器。在这样的处理器平台上,共享同一cache的不同线程之间会产生大量的cache冲突造成cache缺失率(miss rate)上升,程序性能下降。SCP方法将共享cache的存储空间划分成物理上互不相交的子空间,通过cache自身的地址映射机制保证线程的私有数据存放在各自的子空间中,从而有效避免了线程间的cache数据冲突。(3)提出了一种针对NUMA体系结构的混合粒度动态负载均衡方法。由于GEMM计算的规则性,其并行实现一般采用粗粒度的并行策略,将计算负载平均地划分给参与计算的所有线程。在NUMA体系结构上,内存访问的NUMA特性会导致线程执行速度出现不一致的现象,这会使得线程间数据同步开销增加,而GEMM整体性能将受制于最慢的线程。本文提出的混合粒度动态负载均衡方法是一种为GEMM例程专门设计的work-stealing算法,它采用一种粗细粒度结合的负载划分策略,在运行时允许快速线程窃取慢速线程的工作负载以降低线程同步开销。此外,该方法利用GEMM的问题特点,完全避免了队列、树与锁的使用,几乎不引入额外开销。