Files
paddlepaddle--paddle/paddle/phi/kernels/funcs/blas/blas.h
T
2026-07-13 12:40:42 +08:00

693 lines
19 KiB
C++

// Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "paddle/phi/common/bfloat16.h"
#include "paddle/phi/core/dense_tensor.h"
#ifdef PADDLE_WITH_MKLML
#include "paddle/phi/backends/dynload/mklml.h"
#endif
#ifdef PADDLE_WITH_LIBXSMM
#include <libxsmm.h>
#endif
#if defined(PADDLE_USE_OPENBLAS) || defined(PADDLE_USE_REFERENCE_CBLAS)
#include <cblas.h>
#elif defined(PADDLE_WITH_HML)
#include "paddle/phi/backends/dynload/hml.h"
#define CBLAS_LAYOUT CBLAS_ORDER
#elif defined(PADDLE_USE_ACCELERATE)
#include <Accelerate/Accelerate.h>
#define CBLAS_LAYOUT CBLAS_ORDER
#endif
namespace phi {
namespace funcs {
/**
* Matrix Descriptor of a memory buffer.
*
* It is used for Blas::MatMul. MatMul operator can be batched.
* if Mat A is [BatchSize, H, W], Mat B is [BatchSize, H, W]. It will be a
* `batch_size` times of GEMM. The batched GEMM could be faster base on the
* implementation of the blas library. The batch size could be zero. If any
* matrix of `matmul` has a batch size, there will be a batched GEMM, too. e.g.,
* Mat A is [BatchSize, H1, W2], and Mat B [H2, W2], The result matrix will be
* [BatchSize, H1, W2]
*
* The boolean flag, `trans`, describe the memory is the transpose of matrix or
* not. If the trans is true, the last two dims of matrix are transposed. The
* memory layout of the matrix is [Width, Height] or [BatchSize, Width, Height].
*
* The MatDescriptor is not only the dimension or shape of a matrix, it also
* contains the layout, stride of matrix. It is clearer to have a structure than
* reuse `DDim`.
*/
struct MatDescriptor {
int64_t height_;
int64_t width_;
int64_t stride_{0};
int64_t batch_size_{0};
bool trans_;
};
/**
* Create Matrix Descriptor from a tensor dim, num_flatten_cols, and transpose
* flag
*
* @param tensor_dim: The dimension of the tensor. The rank of this dimension
* must larger than 1.
*
* @param num_flatten_cols: Reshape a tensor to a matrix. The matrix's first
* dimension(column length) will be the product of tensor's first `num_col_dims`
* dimensions. If num_flatten_cols is zero, the first N-2 dimension will be the
* batch_size of descriptor.
*
* @param trans: True if the matrix is transposed.
*/
extern PADDLE_API MatDescriptor CreateMatrixDescriptor(const DDim& tensor_dim,
int num_flatten_cols,
bool trans);
template <typename DeviceContext>
class Blas {
public:
explicit Blas(const DeviceContext& dev_ctx) : dev_ctx_(dev_ctx) {}
template <typename T>
void GEMM(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int64_t M,
int64_t N,
int64_t K,
T alpha,
const T* A,
const T* B,
T beta,
T* C) const;
template <typename T, typename U = T>
void GEMM(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int64_t M,
int64_t N,
int64_t K,
U alpha,
const T* A,
const T* B,
U beta,
T* C) const;
void GEMM(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int64_t M,
int64_t N,
int64_t K,
float alpha,
const phi::bfloat16* A,
const phi::bfloat16* B,
float beta,
float* C) const;
template <typename T>
void GEMM(bool transA,
bool transB,
int M,
int N,
int K,
T alpha,
const T* A,
int lda,
const T* B,
int ldb,
T beta,
T* C,
int ldc) const;
template <typename T>
void GEMM(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int M,
int N,
int K,
T alpha,
const T* A,
int lda,
const T* B,
int ldb,
T beta,
T* C,
int ldc) const;
#ifdef PADDLE_WITH_MKLML // @{ Group MKLML: class Blas
template <typename T>
T* GEMM_ALLOC(const CBLAS_IDENTIFIER id,
const int M,
const int N,
const int K) const;
template <typename T>
void GEMM_PACK(const CBLAS_IDENTIFIER id,
const CBLAS_TRANSPOSE trans,
int M,
int N,
int K,
const T alpha,
const T* src,
const int ld,
T* dst) const;
template <typename T>
void GEMM_COMPUTE(int transA,
int transB,
int M,
int N,
int K,
const T* A,
const int lda,
const T* B,
const int ldb,
T beta,
T* C,
const int ldc) const;
template <typename T>
void GEMM_FREE(T* data) const;
template <typename T>
void CSRMM(const char* transa,
const int* m,
const int* n,
const int* k,
const T* alpha,
const char* matdescra,
const T* val,
const int* index,
const int* pntrb,
const int* pntre,
const T* b,
const int* ldb,
const T* beta,
T* c,
const int* ldc) const;
#if !defined(PADDLE_WITH_CUDA) && !defined(PADDLE_WITH_HIP)
template <typename T>
void MatMulWithHead(const DenseTensor& mat_a,
const MatDescriptor& dim_a,
const DenseTensor& mat_b,
const MatDescriptor& dim_b,
T alpha,
int head_number,
DenseTensor* mat_out,
T beta,
bool mat_y_split_vertical) const;
#endif
#endif // @} End Group MKLML: class Blas
#if defined(PADDLE_WITH_HML) && !defined(PADDLE_WITH_CUDA) && \
!defined(PADDLE_WITH_HIP)
template <typename T>
void MatMulWithHead(const DenseTensor& mat_a,
const MatDescriptor& dim_a,
const DenseTensor& mat_b,
const MatDescriptor& dim_b,
T alpha,
int head_number,
DenseTensor* mat_out,
T beta,
bool mat_y_split_vertical) const;
#endif
template <typename T>
void MatMul(const int M,
const int N,
const int K,
const T* A,
const T* B,
T* C) const;
template <typename T>
void MatMul(const DenseTensor& mat_a,
bool trans_a,
const DenseTensor& mat_b,
bool trans_b,
T alpha,
DenseTensor* mat_out,
T beta) const;
template <typename T>
void MatMul(const DenseTensor& mat_a,
bool trans_a,
const DenseTensor& mat_b,
bool trans_b,
DenseTensor* mat_out) const {
MatMul(mat_a,
trans_a,
mat_b,
trans_b,
static_cast<T>(1.0),
mat_out,
static_cast<T>(0.0));
}
template <typename T>
void MatMul(const DenseTensor& mat_a,
const DenseTensor& mat_b,
DenseTensor* mat_out) const {
this->template MatMul<T>(mat_a, false, mat_b, false, mat_out);
}
template <typename T>
void AXPY(int n, T alpha, const T* x, T* y) const;
template <typename T>
void VADD(int n, const T* x, const T* y, T* z) const;
template <typename T>
void VSUB(int n, const T* x, const T* y, T* z) const;
template <typename T>
void VMUL(int n, const T* x, const T* y, T* z) const;
template <typename T>
void VDIV(int n, const T* x, const T* y, T* z) const;
template <typename T>
void VCOPY(int n, const T* x, T* y) const;
template <typename T>
void VEXP(int n, const T* x, T* y) const;
template <typename T>
void VSQUARE(int n, const T* x, T* y) const;
template <typename T>
void VPOW(int n, const T* x, T alpha, T* y) const;
template <typename T>
void GEMV(bool trans_a,
int M,
int N,
T alpha,
const T* A,
const T* B,
T beta,
T* C) const;
template <typename T>
T DOT(int n, const T* x, const T* y) const;
template <typename T>
void CUDOT(
int n, const T* x, int incx, const T* y, int incy, T* result) const;
template <typename T>
void SCAL(int n, const T a, T* x) const;
template <typename T>
T ASUM(int n, T* x, int inc) const;
template <typename T>
void BatchedGEMM(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int64_t M,
int64_t N,
int64_t K,
T alpha,
const T* A,
const T* B,
T beta,
T* C,
int64_t batchCount,
int64_t strideA,
int64_t strideB) const;
template <typename T, typename U = T>
void BatchedGEMM(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int64_t M,
int64_t N,
int64_t K,
U alpha,
const T* A,
const T* B,
U beta,
T* C,
int64_t batchCount,
int64_t strideA,
int64_t strideB) const;
template <typename T>
void BatchedGEMM(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int M,
int N,
int K,
T alpha,
const T** A,
const T** B,
T beta,
T** C,
int batchCount) const;
#if defined(PADDLE_WITH_MKLML) && !defined(PADDLE_WITH_CUDA) && \
!defined(PADDLE_WITH_HIP)
template <typename T>
void BatchedGEMMWithHead(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int W1,
int H1,
int W2,
int H2,
T alpha,
const T* A,
const T* B,
T beta,
T* C,
int batchCount,
int64_t strideA,
int64_t strideB,
int64_t head_number,
bool split_b_vertical) const;
#endif
#if defined(PADDLE_WITH_HML) && !defined(PADDLE_WITH_CUDA) && \
!defined(PADDLE_WITH_HIP)
template <typename T>
void BatchedGEMMWithHead(CBLAS_TRANSPOSE transA,
CBLAS_TRANSPOSE transB,
int W1,
int H1,
int W2,
int H2,
T alpha,
const T* A,
const T* B,
T beta,
T* C,
int batchCount,
int64_t strideA,
int64_t strideB,
int64_t head_number,
bool split_b_vertical) const;
#endif
template <typename T>
void MatMul(const DenseTensor& mat_a,
const MatDescriptor& dim_a,
const DenseTensor& mat_b,
const MatDescriptor& dim_b,
T alpha,
DenseTensor* mat_out,
T beta) const;
template <typename T>
void MatMul(const T* mat_a,
const MatDescriptor& dim_a,
const T* mat_b,
const MatDescriptor& dim_b,
T alpha,
T* mat_out,
T beta) const;
template <typename T>
void VINV(int n, const T* a, T* y) const;
template <typename T>
void VMERF(int n, const T* a, T* y, int64_t mode) const;
template <typename T>
void TRSM(CBLAS_SIDE side,
CBLAS_UPLO uplo,
CBLAS_TRANSPOSE transA,
CBLAS_DIAG diag,
int M,
int N,
T alpha,
const T* A,
int lda,
T* B,
int ldb) const;
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
template <typename T>
void BatchedGETRF(int n, T** a, int* ipiv, int* info, int batch_size) const;
template <typename T>
void BatchedGETRI(int n,
const T** a,
const int* ipiv,
T** a_inv,
int* info,
int batch_size) const;
template <typename T>
void BatchedMatInv(
int n, const T** a, T** a_inv, int* info, int batch_size) const;
// cuBlas solve
template <typename T>
void BatchedGETRS(CBLAS_TRANSPOSE trans,
int n,
int nrhs,
const T** a,
int lda,
int* ipiv,
T** b,
int ldb,
int* info,
int batch_size) const;
// cuBlas triangular_solve
template <typename T>
void BatchedTRSM(CBLAS_SIDE side,
CBLAS_UPLO uplo,
CBLAS_TRANSPOSE transA,
CBLAS_DIAG diag,
int M,
int N,
T alpha,
const T** a,
int lda,
T** b,
int ldb,
int batch_size) const;
#endif
private:
const DeviceContext& dev_ctx_;
};
template <typename DeviceContext, typename T>
class BlasT : private Blas<DeviceContext> {
public:
using Blas<DeviceContext>::Blas;
template <typename... ARGS>
void GEMM(ARGS... args) const {
Base()->template GEMM<T>(args...);
}
#ifdef PADDLE_WITH_MKLML // @{ Group MKLML: class BlasT
template <typename... ARGS>
T* GEMM_ALLOC(ARGS... args) const {
return Base()->template GEMM_ALLOC<T>(args...);
}
template <typename... ARGS>
void GEMM_PACK(ARGS... args) const {
Base()->template GEMM_PACK<T>(args...);
}
template <typename... ARGS>
void GEMM_COMPUTE(ARGS... args) const {
Base()->template GEMM_COMPUTE<T>(args...);
}
template <typename... ARGS>
void GEMM_FREE(ARGS... args) const {
Base()->template GEMM_FREE<T>(args...);
}
template <typename... ARGS>
void CSRMM(ARGS... args) const {
Base()->template CSRMM<T>(args...);
}
#if !defined(PADDLE_WITH_CUDA) && !defined(PADDLE_WITH_HIP)
template <typename... ARGS>
void MatMulWithHead(ARGS... args) const {
Base()->template MatMulWithHead<T>(args...);
}
#endif
#endif // @} End Group MKLML: class BlasT
#if defined(PADDLE_WITH_HML) && !defined(PADDLE_WITH_CUDA) && \
!defined(PADDLE_WITH_HIP)
template <typename... ARGS>
void MatMulWithHead(ARGS... args) const {
Base()->template MatMulWithHead<T>(args...);
}
#endif
template <typename... ARGS>
void MatMul(ARGS... args) const {
Base()->template MatMul<T>(args...);
}
template <typename... ARGS>
void AXPY(ARGS... args) const {
Base()->template AXPY<T>(args...);
}
template <typename... ARGS>
void VADD(ARGS... args) const {
Base()->template VADD<T>(args...);
}
template <typename... ARGS>
void VSUB(ARGS... args) const {
Base()->template VSUB<T>(args...);
}
template <typename... ARGS>
void VMUL(ARGS... args) const {
Base()->template VMUL<T>(args...);
}
template <typename... ARGS>
void VDIV(ARGS... args) const {
Base()->template VDIV<T>(args...);
}
template <typename... ARGS>
void VCOPY(ARGS... args) const {
Base()->template VCOPY<T>(args...);
}
template <typename... ARGS>
void VEXP(ARGS... args) const {
Base()->template VEXP<T>(args...);
}
template <typename... ARGS>
void VSQUARE(ARGS... args) const {
Base()->template VSQUARE<T>(args...);
}
template <typename... ARGS>
void VPOW(ARGS... args) const {
Base()->template VPOW<T>(args...);
}
template <typename... ARGS>
void GEMV(ARGS... args) const {
Base()->template GEMV<T>(args...);
}
template <typename... ARGS>
T DOT(ARGS... args) const {
return Base()->template DOT<T>(args...);
}
template <typename... ARGS>
void CUDOT(ARGS... args) const {
Base()->template CUDOT<T>(args...);
}
template <typename... ARGS>
void SCAL(ARGS... args) const {
Base()->template SCAL<T>(args...);
}
template <typename... ARGS>
T ASUM(ARGS... args) const {
return Base()->template ASUM<T>(args...);
}
template <typename... ARGS>
void BatchedGEMM(ARGS... args) const {
Base()->template BatchedGEMM<T>(args...);
}
template <typename... ARGS>
void VINV(ARGS... args) const {
Base()->template VINV<T>(args...);
}
template <typename... ARGS>
void VMERF(ARGS... args) const {
Base()->template VMERF<T>(args...);
}
template <typename... ARGS>
void TRSM(ARGS... args) const {
Base()->template TRSM<T>(args...);
}
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
template <typename... ARGS>
void BatchedGETRF(ARGS... args) const {
Base()->template BatchedGETRF<T>(args...);
}
template <typename... ARGS>
void BatchedGETRI(ARGS... args) const {
Base()->template BatchedGETRI<T>(args...);
}
template <typename... ARGS>
void BatchedMatInv(ARGS... args) const {
Base()->template BatchedMatInv<T>(args...);
}
// solve
template <typename... ARGS>
void BatchedGETRS(ARGS... args) const {
Base()->template BatchedGETRS<T>(args...);
}
// triangular_solve
template <typename... ARGS>
void BatchedTRSM(ARGS... args) const {
Base()->template BatchedTRSM<T>(args...);
}
#endif
private:
const Blas<DeviceContext>* Base() const {
return static_cast<const Blas<DeviceContext>*>(this);
}
};
template <typename DeviceContext, typename T>
inline BlasT<DeviceContext, T> GetBlas(const DeviceContext& dev_ctx) {
return BlasT<DeviceContext, T>(dev_ctx);
}
} // namespace funcs
} // namespace phi
#include "paddle/phi/kernels/funcs/blas/blas_impl.h"
#ifdef PADDLE_WITH_CUDA
#include "paddle/phi/kernels/funcs/blas/blas_impl.cu.h"
#endif
#ifdef PADDLE_WITH_HIP
#include "paddle/phi/kernels/funcs/blas/blas_impl.hip.h"
#endif