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

201 lines
6.3 KiB
C++

// Copyright (c) 2024 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
#if !defined(PADDLE_WITH_ARM) && !defined(PADDLE_WITH_SW) && \
!defined(PADDLE_WITH_MIPS) && !defined(PADDLE_WITH_LOONGARCH)
#include <immintrin.h>
#endif
#include <cfloat>
#include <cmath>
#include <cstring>
#include "paddle/phi/kernels/funcs/blas/blas.h"
#include "paddle/phi/kernels/funcs/math_function.h"
namespace phi {
namespace funcs {
template <typename DeviceContext, typename T>
void call_gemm(const funcs::BlasT<DeviceContext, T>& blas,
const CBLAS_TRANSPOSE TransA,
const CBLAS_TRANSPOSE TransB,
const int M,
const int N,
const int K,
const T alpha,
const T* A,
const T* B,
const T beta,
T* C) {
int lda = (TransA == CblasNoTrans) ? K : M;
int ldb = (TransB == CblasNoTrans) ? N : K;
blas.GEMM(TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, N);
}
template <typename T, typename Context>
void call_gemm(const Context& dev_ctx,
const CBLAS_TRANSPOSE TransA,
const CBLAS_TRANSPOSE TransB,
const int M,
const int N,
const int K,
const T alpha,
const T* A,
const T* B,
const T beta,
T* C) {
int lda = (TransA == CblasNoTrans) ? K : M;
int ldb = (TransB == CblasNoTrans) ? N : K;
// auto& dev_ctx = dev_ctx.template device_context<CPUContext>();
auto blas = funcs::GetBlas<CPUContext, T>(dev_ctx);
blas.GEMM(TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, N);
}
template <typename DeviceContext, typename T>
void call_gemm_with_lda(const funcs::BlasT<DeviceContext, T>& blas,
const CBLAS_TRANSPOSE TransA,
const CBLAS_TRANSPOSE TransB,
const int M,
const int N,
const int K,
const T alpha,
const T* A,
const T* B,
const T beta,
T* C,
int lda) {
int ldb = (TransB == CblasNoTrans) ? N : K;
blas.GEMM(TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, N);
}
template <typename T, typename Context>
void call_gemm_batched(const Context& dev_ctx,
const CBLAS_TRANSPOSE TransA,
const CBLAS_TRANSPOSE TransB,
const int M,
const int N,
const int K,
const T alpha,
const T** A,
const T** B,
const T beta,
T** C,
const int batch) {
for (int i = 0; i < batch; ++i) {
call_gemm(dev_ctx, TransA, TransB, M, N, K, alpha, A[i], B[i], beta, C[i]);
}
}
#if !defined(PADDLE_WITH_ARM) && !defined(PADDLE_WITH_SW) && \
!defined(PADDLE_WITH_MIPS) && !defined(PADDLE_WITH_LOONGARCH)
#define __m256x __m256
static const unsigned int AVX_STEP_SIZE = 8;
static const unsigned int AVX_CUT_LEN_MASK = 7U;
#define _mm256_mul_px _mm256_mul_ps
#define _mm256_add_px _mm256_add_ps
#define _mm256_load_px _mm256_loadu_ps
#define _mm256_store_px _mm256_storeu_ps
#define _mm256_broadcast_sx _mm256_broadcast_ss
#define __m128x __m128
static const unsigned int SSE_STEP_SIZE = 2;
static const unsigned int SSE_CUT_LEN_MASK = 1U;
#define _mm_add_px _mm_add_ps
#define _mm_mul_px _mm_mul_ps
#define _mm_load_px _mm_loadu_ps
#define _mm_store_px _mm_storeu_ps
#define _mm_load1_px _mm_load1_ps
#endif
template <typename T>
inline void axpy(const T* x, T* y, size_t len, const T alpha) {
unsigned int jjj, lll;
jjj = lll = 0;
#ifdef PADDLE_WITH_AVX
lll = len & ~AVX_CUT_LEN_MASK;
__m256x mm_alpha = _mm256_broadcast_sx(&alpha);
for (jjj = 0; jjj < lll; jjj += AVX_STEP_SIZE) {
_mm256_store_px(
y + jjj,
_mm256_add_px(_mm256_load_px(y + jjj),
_mm256_mul_px(mm_alpha, _mm256_load_px(x + jjj))));
}
#elif defined(PADDLE_WITH_ARM) || defined(PADDLE_WITH_SW) || \
defined(PADDLE_WITH_MIPS) || defined(PADDLE_WITH_LOONGARCH)
PADDLE_THROW(common::errors::Unimplemented("axpy is not supported"));
#else
lll = len & ~SSE_CUT_LEN_MASK;
__m128x mm_alpha = _mm_load1_px(&alpha);
for (jjj = 0; jjj < lll; jjj += SSE_STEP_SIZE) {
_mm_store_px(y + jjj,
_mm_add_px(_mm_load_px(y + jjj),
_mm_mul_px(mm_alpha, _mm_load_px(x + jjj))));
}
#endif
for (; jjj < len; jjj++) {
y[jjj] += alpha * x[jjj];
}
}
template <typename T>
inline void axpy_noadd(const T* x, T* y, size_t len, const T alpha) {
unsigned int jjj, lll;
jjj = lll = 0;
#ifdef PADDLE_WITH_AVX
lll = len & ~AVX_CUT_LEN_MASK;
__m256x mm_alpha = _mm256_broadcast_sx(&alpha);
for (jjj = 0; jjj < lll; jjj += AVX_STEP_SIZE) {
_mm256_store_px(y + jjj, _mm256_mul_px(mm_alpha, _mm256_load_px(x + jjj)));
}
#elif defined(PADDLE_WITH_ARM) || defined(PADDLE_WITH_SW) || \
defined(PADDLE_WITH_MIPS) || defined(PADDLE_WITH_LOONGARCH)
PADDLE_THROW(common::errors::Unimplemented("axpy_noadd is not supported"));
#else
lll = len & ~SSE_CUT_LEN_MASK;
__m128x mm_alpha = _mm_load1_px(&alpha);
for (jjj = 0; jjj < lll; jjj += SSE_STEP_SIZE) {
_mm_store_px(y + jjj, _mm_mul_px(mm_alpha, _mm_load_px(x + jjj)));
}
#endif
for (; jjj < len; jjj++) {
y[jjj] = alpha * x[jjj];
}
}
inline void axpy_noadd(const int8_t* x,
int8_t* y,
size_t len,
const float alpha) {
PADDLE_THROW(common::errors::Unimplemented(
"int8_t input of axpy_noadd is not supported"));
}
} // namespace funcs
} // namespace phi