remove neural-speed (#22236)

### Description
<!-- Describe your changes. -->
NS is not developed anymore and ORT doesn't use it for int4 inference
either. Remove it to clean up the code


### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
This commit is contained in:
Yufeng Li 2024-10-01 09:50:44 -07:00 committed by GitHub
parent 50bda44a70
commit 96e9c99dce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 5 additions and 1078 deletions

View file

@ -202,16 +202,6 @@
"comments": "mp11"
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "150e7527d5286ddd3a995c228dedf8d76a7a86bc",
"repositoryUrl": "https://github.com/intel/neural-speed.git"
},
"comments": "neural_speed"
}
},
{
"component": {
"type": "git",

View file

@ -96,7 +96,6 @@ option(onnxruntime_USE_QNN "Build with QNN support" OFF)
option(onnxruntime_USE_SNPE "Build with SNPE support" OFF)
option(onnxruntime_USE_RKNPU "Build with RKNPU support" OFF)
option(onnxruntime_USE_DNNL "Build with DNNL support" OFF)
option(onnxruntime_USE_NEURAL_SPEED "Build with Neural Speed support" OFF)
option(onnxruntime_USE_JSEP "Build with JavaScript implemented kernels support" OFF)
option(onnxruntime_BUILD_UNIT_TESTS "Build ONNXRuntime unit tests" ON)
option(onnxruntime_BUILD_CSHARP "Build C# library" OFF)
@ -979,10 +978,6 @@ function(onnxruntime_set_compile_flags target_name)
target_compile_definitions(${target_name} PRIVATE ENABLE_ATEN)
endif()
if(USE_NEURAL_SPEED)
target_compile_definitions(${target_name} PRIVATE ORT_NEURAL_SPEED)
endif()
set_target_properties(${target_name} PROPERTIES COMPILE_WARNING_AS_ERROR ON)
if (onnxruntime_USE_CUDA)
# Suppress a "conversion_function_not_usable" warning in gsl/span
@ -1263,13 +1258,6 @@ if (onnxruntime_USE_DNNL)
add_compile_definitions(DNNL_OPENMP)
endif()
if (onnxruntime_USE_NEURAL_SPEED AND NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_USE_TVM)
include(neural_speed)
if (USE_NEURAL_SPEED)
list(APPEND onnxruntime_EXTERNAL_LIBRARIES neural_speed::bestla)
endif()
endif()
# TVM EP
if (onnxruntime_USE_TVM)
if (NOT TARGET tvm)

View file

@ -36,7 +36,6 @@ microsoft_gsl;https://github.com/microsoft/GSL/archive/refs/tags/v4.0.0.zip;cf36
microsoft_wil;https://github.com/microsoft/wil/archive/refs/tags/v1.0.230629.1.zip;e4a542a323c070376f7c2d1973d0f7ddbc1d2fa5
mimalloc;https://github.com/microsoft/mimalloc/archive/refs/tags/v2.1.1.zip;d5ee7d34223d0567892db5179849939c8769dc41
mp11;https://github.com/boostorg/mp11/archive/refs/tags/boost-1.82.0.zip;9bc9e01dffb64d9e0773b2e44d2f22c51aace063
neural_speed;https://github.com/intel/neural-speed/archive/refs/tags/v0.3.zip;5ec64e3071edc7347ebd8a81679cf06e2bb9b851
onnx;https://github.com/onnx/onnx/archive/refs/tags/v1.16.1.zip;2eb9198bb352757d5ff13977cbe0634898e0837c
# Use the latest commit of 10.4-GA-ORT-DDS
onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/9f98e2ebe7507fe0774d06a44bbf4b0e82cc9ce7.zip;1d92137f424513bce20033ab4fb31cc0be8d1185

View file

@ -1,16 +0,0 @@
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND onnxruntime_target_platform STREQUAL "x86_64")
set(USE_NEURAL_SPEED TRUE)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" AND onnxruntime_target_platform STREQUAL "x64")
set(USE_NEURAL_SPEED TRUE)
endif()
if(USE_NEURAL_SPEED)
FetchContent_Declare(
neural_speed
URL ${DEP_URL_neural_speed}
URL_HASH SHA1=${DEP_SHA1_neural_speed}
PATCH_COMMAND ${Patch_EXECUTABLE} -p1 < ${PROJECT_SOURCE_DIR}/patches/neural_speed/150e7527d5286ddd3a995c228dedf8d76a7a86bc.patch
)
set(BTLA_USE_OPENMP OFF)
onnxruntime_fetchcontent_makeavailable(neural_speed)
endif()

View file

@ -60,15 +60,6 @@ if(NOT onnxruntime_DISABLE_CONTRIB_OPS)
"${ONNXRUNTIME_ROOT}/contrib_ops/cpu/aten_ops/aten_op_executor.cc"
)
endif()
set(onnxruntime_cpu_neural_speed_srcs
"${ONNXRUNTIME_ROOT}/contrib_ops/cpu/quantization/neural_speed_wrapper.h"
"${ONNXRUNTIME_ROOT}/contrib_ops/cpu/quantization/neural_speed_defs.h"
"${ONNXRUNTIME_ROOT}/contrib_ops/cpu/quantization/neural_speed_gemm.cc"
"${ONNXRUNTIME_ROOT}/contrib_ops/cpu/quantization/neural_speed_gemm.h"
)
if(NOT USE_NEURAL_SPEED)
list(REMOVE_ITEM onnxruntime_cpu_contrib_ops_srcs ${onnxruntime_cpu_neural_speed_srcs})
endif()
# add using ONNXRUNTIME_ROOT so they show up under the 'contrib_ops' folder in Visual Studio
source_group(TREE ${ONNXRUNTIME_ROOT} FILES ${onnxruntime_cpu_contrib_ops_srcs})
list(APPEND onnxruntime_providers_src ${onnxruntime_cpu_contrib_ops_srcs})
@ -153,12 +144,6 @@ if (HAS_BITWISE_INSTEAD_OF_LOGICAL)
target_compile_options(onnxruntime_providers PRIVATE "-Wno-bitwise-instead-of-logical")
endif()
if(NOT onnxruntime_DISABLE_CONTRIB_OPS)
if(USE_NEURAL_SPEED)
onnxruntime_add_include_to_target(onnxruntime_providers neural_speed::bestla)
endif()
endif()
if (MSVC)
target_compile_options(onnxruntime_providers PRIVATE "/bigobj")
# if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)

View file

@ -1,30 +0,0 @@
diff --git a/bestla/bestla/bestla_prologue_b.h b/bestla/bestla/bestla_prologue_b.h
index 99f3ccc..a11de9d 100644
--- a/bestla/bestla/bestla_prologue_b.h
+++ b/bestla/bestla/bestla_prologue_b.h
@@ -456,9 +456,8 @@ class WeightKBlockNInteger {
auto tmpscales = tmp;
auto tmpzeropoints = reinterpret_cast<int8_t*>(tmpscales + N * blks);
if (scales) {
- for (size_t i = 0; i < N * blks; i += 2) {
+ for (size_t i = 0; i < N * blks; i ++) {
tmpscales[i] = scales[i] / 16;
- tmpscales[i + 1] = scales[i + 1] / 16;
}
}
if (zero_points) {
diff --git a/bestla/bestla/kernel_avx512f.h b/bestla/bestla/kernel_avx512f.h
index 6783ee8..59822e5 100644
--- a/bestla/bestla/kernel_avx512f.h
+++ b/bestla/bestla/kernel_avx512f.h
@@ -673,8 +673,8 @@ inline BTLA_CODE decompress_kblock_s3_s8fp(utils::bit2x4* bit2ptr, utils::bit1x8
zmm1 = _mm512_sllv_epi32(zmm1, zmm_shift); // int3_clip => int8
zmm2 = _mm512_sllv_epi32(zmm2, zmm_shift); // int3_clip => int8
- _mm512_storeu_epi8((__m512i*)dst, zmm1);
- _mm512_storeu_epi8((__m512i*)(dst + 64), zmm2);
+ _mm512_storeu_si512((__m512i*)dst, zmm1);
+ _mm512_storeu_si512((__m512i*)(dst + 64), zmm2);
};
assert(head_ignore_num % 8 == 0);

View file

@ -16,10 +16,6 @@
#include "core/providers/cpu/math/matmul_helper.h"
#include "core/providers/common.h"
#ifdef ORT_NEURAL_SPEED
#include "contrib_ops/cpu/quantization/neural_speed_gemm.h"
#endif
namespace onnxruntime {
namespace contrib {
@ -41,16 +37,6 @@ int64_t GetAccuracyLevel(size_t nbits, size_t block_size, int64_t accuracy_level
static_cast<int64_t>(CompMostAccurate),
static_cast<int64_t>(CompLeastAccurate));
#if defined(ORT_NEURAL_SPEED)
ORT_UNUSED_PARAMETER(nbits);
ORT_UNUSED_PARAMETER(block_size);
// Neural Speed APIs already expect a minimum accuracy level so just use the given value.
return accuracy_level;
#else // defined(ORT_NEURAL_SPEED)
// Find a supported accuracy level that is not less accurate than the one given.
// CompMostAccurate is always supported with the fallback implementation.
// Note: A higher numeric accuracy level value means lower accuracy, so the comparison order is reversed.
@ -63,8 +49,6 @@ int64_t GetAccuracyLevel(size_t nbits, size_t block_size, int64_t accuracy_level
}
return effective_accuracy_level;
#endif // defined(ORT_NEURAL_SPEED)
}
} // namespace
@ -109,15 +93,6 @@ class MatMulNBits final : public OpKernel {
"Only 4b quantization is supported for MatMulNBits op, additional bits support is planned.");
const Tensor* tensor_zero_point = nullptr;
has_zp_input_ = info.TryGetConstantInput(InputIndex::zero_points, &tensor_zero_point);
#ifdef ORT_NEURAL_SPEED
const Tensor* tensor_B = nullptr;
const Tensor* tensor_scale = nullptr;
bool B_constant = info.TryGetConstantInput(InputIndex::B, &tensor_B);
bool scale_constant = info.TryGetConstantInput(InputIndex::scales, &tensor_scale);
is_asym_ = zero_point_arg != nullptr;
all_constant_ = B_constant && scale_constant;
all_constant_ = is_asym_ ? all_constant_ && has_zp_input_ : all_constant_;
#endif
}
Status Compute(OpKernelContext* context) const override;
@ -146,12 +121,6 @@ class MatMulNBits final : public OpKernel {
IAllocatorUniquePtr<float> bias_fp32_{};
bool has_zp_input_{false};
#if defined(ORT_NEURAL_SPEED)
bool is_asym_{false};
bool all_constant_{false};
#endif // defined(ORT_NEURAL_SPEED)
// dequantize B first and then compute float gemm
Status ComputeBUnpacked(const Tensor* a,
@ -179,71 +148,6 @@ class MatMulNBits final : public OpKernel {
}
};
#if defined(ORT_NEURAL_SPEED)
template <typename T1>
Status MatMulNBits<T1>::PrePack(const Tensor& tensor, int input_idx, /*out*/ AllocatorPtr alloc,
/*out*/ bool& is_packed,
/*out*/ PrePackedWeights* prepacked_weights) {
is_packed = false;
if (has_g_idx_ || has_unquantized_zero_point_) {
return Status::OK();
}
if (!all_constant_) {
return Status::OK();
}
if (has_bias_) { // adding bias is not supported
return Status::OK();
}
if (nbits_ != 4) {
return Status::OK();
}
MLAS_THREADPOOL* pool = nullptr;
auto nbits = static_cast<int>(nbits_);
if (input_idx == InputIndex::B) {
packed_b_size_ = NSNBitsGemmPackBSize(N_, K_, block_size_, nbits, is_asym_, compute_type_);
if (packed_b_size_ == 0) return Status::OK();
auto qptr = tensor.Data<uint8_t>();
packed_b_ = IAllocator::MakeUniquePtr<void>(alloc, packed_b_size_, true);
std::memset(packed_b_.get(), 0, packed_b_size_);
NSNBitsGemmPackB(packed_b_.get(), qptr, nullptr, nullptr, N_, K_, K_, block_size_, nbits, is_asym_, false,
compute_type_, pool);
if (prepacked_weights) {
prepacked_weights->buffers_.push_back(std::move(packed_b_));
prepacked_weights->buffer_sizes_.push_back(packed_b_size_);
}
is_packed = true;
}
if (input_idx == InputIndex::scales && packed_b_ != nullptr) {
auto sptr = tensor.Data<float>();
NSNBitsGemmPackB(packed_b_.get(), nullptr, sptr, nullptr, N_, K_, K_, block_size_, nbits, is_asym_, !is_asym_,
compute_type_, pool);
if (prepacked_weights) {
prepacked_weights->buffers_.push_back(std::move(packed_b_));
prepacked_weights->buffer_sizes_.push_back(packed_b_size_);
}
is_packed = true;
}
if (input_idx == InputIndex::zero_points && packed_b_ != nullptr) {
auto zptr = tensor.Data<uint8_t>();
NSNBitsGemmPackB(packed_b_.get(), nullptr, nullptr, zptr, N_, K_, K_, block_size_, nbits, is_asym_, is_asym_,
compute_type_, pool);
if (prepacked_weights) {
prepacked_weights->buffers_.push_back(std::move(packed_b_));
prepacked_weights->buffer_sizes_.push_back(packed_b_size_);
}
is_packed = true;
}
return Status::OK();
}
#else // defined(ORT_NEURAL_SPEED)
template <typename T1>
Status MatMulNBits<T1>::PrePack(const Tensor& tensor, int input_idx, /*out*/ AllocatorPtr alloc,
/*out*/ bool& is_packed,
@ -338,37 +242,15 @@ Status MatMulNBits<MLFloat16>::PrePack(const Tensor& tensor, int input_idx, /*ou
return Status::OK();
}
#endif // !defined(ORT_NEURAL_SPEED)
template <typename T1>
Status MatMulNBits<T1>::UseSharedPrePackedBuffers(std::vector<BufferUniquePtr>& prepacked_buffers, int input_idx,
/*out*/ bool& used_shared_buffers) {
used_shared_buffers = false;
#if defined(ORT_NEURAL_SPEED)
// Pack three tensors into one buffer
if (input_idx == 1) {
used_shared_buffers = true;
packed_b_ = std::move(prepacked_buffers[0]);
}
if (input_idx == 2) {
used_shared_buffers = true;
packed_b_ = std::move(prepacked_buffers[0]);
}
if (input_idx == 3) {
used_shared_buffers = true;
packed_b_ = std::move(prepacked_buffers[0]);
}
#else // defined(ORT_NEURAL_SPEED)
if (input_idx == 1) {
used_shared_buffers = true;
packed_b_ = std::move(prepacked_buffers[0]);
}
#endif // defined(ORT_NEURAL_SPEED)
return Status::OK();
}
@ -776,32 +658,9 @@ Status MatMulNBits<T1>::Compute(OpKernelContext* ctx) const {
// If this changes, i.e., if MlasIsSQNBitGemmAvailable() can return true while
// MlasSQNBitGemmPackQuantBDataSize() returns 0, we can consider calling MlasSQNBitGemmBatch()
// with B directly too.
#if defined(ORT_NEURAL_SPEED)
const auto* a_data = a->Data<T1>();
auto* y_data = y->MutableData<T1>();
const size_t batch_count = helper.OutputOffsets().size();
const size_t M = static_cast<size_t>(helper.M());
const size_t N = static_cast<size_t>(helper.N());
const size_t K = static_cast<size_t>(helper.K());
const size_t lda = helper.Lda(false);
InlinedVector<NS_SQNBITS_GEMM_DATA_PACKED_PARAMS> gemm_params(batch_count);
for (size_t i = 0; i < batch_count; i++) {
gemm_params[i].A = a_data + helper.LeftOffsets()[i];
gemm_params[i].lda = lda;
gemm_params[i].B = packed_b_.get();
gemm_params[i].C = y_data + helper.OutputOffsets()[i];
gemm_params[i].ldc = N;
}
auto ws_size = NSSQNBitsGemmBatchWorkspaceSize(M, N, K, batch_count, gemm_params.data());
// workspace for activation process(dynamic quantization and others)
auto ws_ptr = IAllocator::MakeUniquePtr<int8_t>(allocator, ws_size);
NSSQNBitsGemmBatchPackedB(M, N, K, batch_count, gemm_params.data(), ws_ptr.get(), thread_pool);
return Status::OK();
#else // defined(ORT_NEURAL_SPEED)
if (MlasIsSQNBitGemmAvailable(nbits_, block_size_, compute_type_)) {
return ComputeBPacked(a, scales, zero_points, bias, y, allocator, thread_pool, helper);
}
#endif // !defined(ORT_NEURAL_SPEED)
}
// If B is prepacked, B would have been removed from the context

View file

@ -1,45 +0,0 @@
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
--*/
#pragma once
#include "contrib_ops/cpu/quantization/neural_speed_wrapper.h"
namespace bestla {
using tAVX512F = gemm::SCoreRowNAvx512f<48, 8>;
using tAMX_BF16 = gemm::HCoreRowNAmxbf16<64, 16>;
using tAVX512_FP16 = gemm::HCoreRowNAvx512fp16<96, 8>;
using tAVX_VNNI = gemm::ICoreRowNAvxvnni<24, 4>;
using tAVX512_VNNI = gemm::ICoreRowNAvx512vnni<48, 8>;
using tAMX_INT8_US = gemm::ICoreRowNAmxint8<64, 16>;
using tAMX_INT8_SS = gemm::ICoreRowNAmxint8SS<64, 16>;
using tAVX2 = gemm::SCoreRowNAvx2<24, 4>;
using tAVX_VNNI_KBlock = gemm::ICoreRowNAvxvnniKBlock<24, 2>;
using tAVX512_VNNI_KBlock = gemm::ICoreRowNAvx512vnniKBlock<48, 4>;
using tAMX_INT8_US_KBlock = gemm::ICoreRowNAmxint8KBlock<48, 16>;
using tAMX_INT8_SS_KBlock = gemm::ICoreRowNAmxint8SSKBlock<48, 16>;
template <class GC_T, BTLA_ISA ISA_T>
using tWeiNInt = prologue_b::gemm::WeightKBlockNInteger<GC_T, ISA_T>;
template <class GC_T, BTLA_ISA ISA_T>
using tWeiNFloat = prologue_b::gemm::WeightKBlockNFloat<GC_T, ISA_T>;
class ORTThreading : public parallel::IThreading {
public:
explicit ORTThreading(void* tp);
void parallel_for(const parallel::thread_func& func) const override;
void set_threads(int nthreads) override {
(void)(nthreads);
assert(0);
}
void sync() const override { assert(0); }
void* mTp;
};
} // namespace bestla

View file

@ -1,438 +0,0 @@
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
Module Name:
neural_speed_gemm.cpp
Abstract:
GEMM template combinations of neural_speed.
--*/
#include "contrib_ops/cpu/quantization/neural_speed_defs.h"
#include "contrib_ops/cpu/quantization/neural_speed_gemm.h"
#include "core/platform/threadpool.h"
using ThreadPool = onnxruntime::concurrency::ThreadPool;
namespace bestla {
ORTThreading::ORTThreading(void* tp)
: IThreading(ThreadPool::DegreeOfParallelism(reinterpret_cast<ThreadPool*>(tp))), mTp(tp) {}
void ORTThreading::parallel_for(const parallel::thread_func& func) const {
ThreadPool::TrySimpleParallelFor(reinterpret_cast<ThreadPool*>(mTp), mThreadNum,
[&](ptrdiff_t tid) { func(static_cast<int>(tid)); });
}
template <class GemmCore_T>
static void NSSQ4GemmCompF32(size_t M, size_t N, size_t K, const float* A, size_t lda,
storage::gemm::StorageWeightKBlockNInteger* B, float* C, size_t ldc, int8_t* WorkSpace,
parallel::IThreading* th) {
auto M_ = static_cast<int>(M);
auto N_ = static_cast<int>(N);
auto K_ = static_cast<int>(K);
auto lda_ = static_cast<int>(lda);
auto ldc_ = static_cast<int>(ldc);
utils::GemmProblem gp(1, M_, N_, K_, B->mBlockSize);
if (M <= 16) {
using Parallel = parallel::gemm::SchedulerKBlock<GemmCore_T>;
using Launcher =
wrapper::gemm::LauncherKBlock<GemmCore_T::ISA, GemmCore_T, prologue_a::gemm::ActivationKBlockBaseF32,
prologue_b::gemm::WeightKBlockNInteger, epilogue::gemm::CompFp32BlockEpilogue,
epilogue::gemm::AccumulatorWriteBackFp32>;
static Launcher kernel;
auto reduceA = kernel.mProA.createStorage(M_, K_, B->mBlockSize);
if (B->IsAsym()) {
reduceA.assign(WorkSpace);
ORTThreading single(nullptr);
kernel.mProA.reduce({A, lda_, &reduceA}, M_, K_, B->mBlockSize, &single);
}
typename Launcher::Param args{gp,
{A, lda_, &reduceA},
{B},
{B->template SPtr<int8_t>(), B->SDtype(), B->CStep(), B->template ZPtr<int8_t>(),
reduceA.template RPtr<float>(), reduceA.lda},
{C, ldc_, nullptr}};
parallel::GemmRun<Parallel>(kernel, args, th);
} else {
using Parallel = parallel::gemm::SchedulerBase<GemmCore_T>;
using Launcher =
wrapper::gemm::LauncherBase<GemmCore_T::ISA, GemmCore_T, prologue_a::gemm::ActivationBase,
prologue_b::gemm::WeightKBlockNInteger, epilogue::gemm::AccumulatorWriteBackFp32>;
static Launcher kernel;
typename Launcher::Param args{gp, {A, lda_}, {B}, {C, ldc_, nullptr}};
parallel::GemmRun<Parallel>(kernel, args, th);
}
}
template <class GemmCore_T>
static void NSSQ4GemmCompInt8(size_t M, size_t N, size_t K, const float* A, size_t lda,
storage::gemm::StorageWeightKBlockNInteger* B, float* C, size_t ldc, int8_t* WorkSpace,
parallel::IThreading* th) {
using Parallel = parallel::gemm::SchedulerKBlockS<GemmCore_T>;
using Launcher =
wrapper::gemm::LauncherIntKBlock<GemmCore_T::ISA, GemmCore_T, prologue_a::gemm::ActivationF32KBlockQuantize,
prologue_b::gemm::WeightKBlockNInteger,
epilogue::gemm::AccumulatorWriteBackFp32>;
auto M_ = static_cast<int>(M);
auto N_ = static_cast<int>(N);
auto K_ = static_cast<int>(K);
auto lda_ = static_cast<int>(lda);
auto ldc_ = static_cast<int>(ldc);
static Launcher kernel;
auto quanA = kernel.mProA.createStorage(M_, K_, B->mBlockSize, B->IsAsym());
quanA.assign(WorkSpace);
if (M <= 16) {
ORTThreading single(nullptr);
kernel.mProA.quantize({A, lda_, &quanA}, M_, K_, &single);
} else {
kernel.mProA.quantize({A, lda_, &quanA}, M_, K_, th);
}
utils::GemmProblem gp(1, M_, N_, K_, B->mBlockSize);
typename Launcher::Param args{gp, {A, lda_, &quanA}, {B}, {C, ldc_, nullptr}};
parallel::GemmRun<Parallel>(kernel, args, th);
}
template <class GemmCore_T>
static size_t NSSQ4GemmCompF32WorkspaceSize(size_t M, size_t N, size_t K, const float* A, size_t lda,
storage::gemm::StorageWeightKBlockNInteger* B, float* C, size_t ldc) {
auto M_ = static_cast<int>(M);
auto K_ = static_cast<int>(K);
(void)(A);
(void)(N);
(void)(C);
(void)(lda);
(void)(ldc);
if (M <= 16) {
using ProA = prologue_a::gemm::ActivationKBlockBaseF32<GemmCore_T, GemmCore_T::ISA>;
static ProA proA;
if (B->IsAsym()) {
auto reduceA = proA.createStorage(M_, K_, B->mBlockSize);
return reduceA.mSize;
}
return 0;
} else {
// using ProA = prologue_a::gemm::ActivationBase<GemmCore_T, GemmCore_T::ISA>;
return 0;
}
}
template <class GemmCore_T>
static size_t NSSQ4GemmCompInt8WorkspaceSize(size_t M, size_t N, size_t K, const float* A, size_t lda,
storage::gemm::StorageWeightKBlockNInteger* B, float* C, size_t ldc) {
(void)(N);
(void)(lda);
(void)(ldc);
(void)(A);
(void)(C);
using ProA = prologue_a::gemm::ActivationF32KBlockQuantize<GemmCore_T, GemmCore_T::ISA>;
static ProA proA;
auto quanA =
proA.createStorage(static_cast<int>(M), static_cast<int>(K), static_cast<int>(B->mBlockSize), B->IsAsym());
return quanA.mSize;
}
} // namespace bestla
using namespace bestla;
static bool NSSQ4GemmBatchDriver(size_t M, size_t N, size_t K, size_t BatchN,
const NS_SQNBITS_GEMM_DATA_PACKED_PARAMS* DataParams, int8_t* WorkSpace,
void* ThreadPool) {
GetCPUDevice();
bestla::ORTThreading orth(ThreadPool);
bool processed = true;
for (size_t i = 0; i < BatchN; i++) {
auto ptr = bestla::storage::gemm::PackedWeightParser::deserialBuffer(DataParams[i].B);
auto uptr = std::unique_ptr<bestla::storage::gemm::IWeightBase>(ptr);
if (ptr) {
auto NTile = gemm::CoreAttr::get_mask_val(ptr->mCoreId, gemm::CoreAttr::NTILE_MASK, gemm::CoreAttr::NTILE_SHIFT);
auto PackRow = gemm::CoreAttr::get_packrow(ptr->mCoreId);
auto CType = gemm::CoreAttr::get_comp(ptr->mCoreId);
auto btype = static_cast<gemm::CompType>(gemm::CompTypeHelper::get_B(CType));
if (ptr->mPrologueID == BTLA_PROLOGUEB_IDS::WeightKBlockNInteger) {
auto kptr = reinterpret_cast<bestla::storage::gemm::StorageWeightKBlockNInteger*>(ptr);
auto BlkSize = kptr->mBlockSize;
if (btype == gemm::CompType::tFP32 && PackRow == 1) {
if (NTile == bestla::tAVX512F::NTILE && _cd->AVX512F() && BlkSize % tAVX512F::KTILE == 0) {
bestla::NSSQ4GemmCompF32<bestla::tAVX512F>(M, N, K, DataParams[i].A, DataParams[i].lda, kptr,
DataParams[i].C, DataParams[i].ldc, WorkSpace, &orth);
} else if (NTile == bestla::tAVX2::NTILE && _cd->AVX2() && BlkSize % tAVX2::KTILE == 0) {
bestla::NSSQ4GemmCompF32<bestla::tAVX2>(M, N, K, DataParams[i].A, DataParams[i].lda, kptr, DataParams[i].C,
DataParams[i].ldc, WorkSpace, &orth);
}
}
if (btype == gemm::CompType::tS8 && PackRow == 4) {
if (NTile == bestla::tAMX_INT8_SS_KBlock::NTILE && _cd->AMX_INT8() &&
BlkSize % tAMX_INT8_SS_KBlock::KTILE == 0) {
bestla::NSSQ4GemmCompInt8<bestla::tAMX_INT8_SS_KBlock>(M, N, K, DataParams[i].A, DataParams[i].lda, kptr,
DataParams[i].C, DataParams[i].ldc, WorkSpace,
&orth);
} else if (NTile == bestla::tAVX512_VNNI_KBlock::NTILE && _cd->AVX512_VNNI() &&
BlkSize % tAVX512_VNNI_KBlock::KTILE == 0) {
bestla::NSSQ4GemmCompInt8<bestla::tAVX512_VNNI_KBlock>(M, N, K, DataParams[i].A, DataParams[i].lda, kptr,
DataParams[i].C, DataParams[i].ldc, WorkSpace,
&orth);
} else if (NTile == bestla::tAVX_VNNI_KBlock::NTILE && _cd->AVX_VNNI() &&
BlkSize % tAVX_VNNI_KBlock::KTILE == 0) {
bestla::NSSQ4GemmCompInt8<bestla::tAVX_VNNI_KBlock>(M, N, K, DataParams[i].A, DataParams[i].lda, kptr,
DataParams[i].C, DataParams[i].ldc, WorkSpace, &orth);
}
}
}
} else {
processed = false;
break;
}
}
return processed;
}
static size_t NSSQ4GemmBatchWorkspaceSize(size_t M, size_t N, size_t K, size_t BatchN,
const NS_SQNBITS_GEMM_DATA_PACKED_PARAMS* DataParams) {
GetCPUDevice();
size_t size = 0;
for (size_t i = 0; i < BatchN; i++) {
auto ptr = storage::gemm::PackedWeightParser::deserialBuffer(DataParams[i].B);
auto uptr = std::unique_ptr<storage::gemm::IWeightBase>(ptr);
if (ptr) {
if (ptr->mPrologueID == BTLA_PROLOGUEB_IDS::WeightKBlockNInteger) {
auto kptr = reinterpret_cast<storage::gemm::StorageWeightKBlockNInteger*>(ptr);
auto NTile =
gemm::CoreAttr::get_mask_val(ptr->mCoreId, gemm::CoreAttr::NTILE_MASK, gemm::CoreAttr::NTILE_SHIFT);
auto PackRow = gemm::CoreAttr::get_packrow(ptr->mCoreId);
auto CType = gemm::CoreAttr::get_comp(ptr->mCoreId);
auto btype = static_cast<gemm::CompType>(gemm::CompTypeHelper::get_B(CType));
auto BlkSize = kptr->mBlockSize;
if (btype == gemm::CompType::tFP32 && PackRow == 1) {
if (NTile == tAVX512F::NTILE && _cd->AVX512F() && BlkSize % tAVX512F::KTILE == 0) {
size = std::max(NSSQ4GemmCompF32WorkspaceSize<tAVX512F>(M, N, K, DataParams[i].A, DataParams[i].lda, kptr,
DataParams[i].C, DataParams[i].ldc),
size);
} else if (NTile == tAVX2::NTILE && _cd->AVX2() && BlkSize % tAVX2::KTILE == 0) {
size = std::max(NSSQ4GemmCompF32WorkspaceSize<tAVX2>(M, N, K, DataParams[i].A, DataParams[i].lda, kptr,
DataParams[i].C, DataParams[i].ldc),
size);
}
}
if (btype == gemm::CompType::tS8 && PackRow == 4) {
if (NTile == tAMX_INT8_SS_KBlock::NTILE && _cd->AMX_INT8() && BlkSize % tAMX_INT8_SS_KBlock::KTILE == 0) {
size = std::max(NSSQ4GemmCompInt8WorkspaceSize<tAMX_INT8_SS_KBlock>(
M, N, K, DataParams[i].A, DataParams[i].lda, kptr, DataParams[i].C, DataParams[i].ldc),
size);
} else if (NTile == tAVX512_VNNI_KBlock::NTILE && _cd->AVX512_VNNI() &&
BlkSize % tAVX512_VNNI_KBlock::KTILE == 0) {
size = std::max(NSSQ4GemmCompInt8WorkspaceSize<tAVX512_VNNI_KBlock>(
M, N, K, DataParams[i].A, DataParams[i].lda, kptr, DataParams[i].C, DataParams[i].ldc),
size);
} else if (NTile == tAVX_VNNI_KBlock::NTILE && _cd->AVX_VNNI() && BlkSize % tAVX_VNNI_KBlock::KTILE == 0) {
size = std::max(NSSQ4GemmCompInt8WorkspaceSize<tAVX_VNNI_KBlock>(
M, N, K, DataParams[i].A, DataParams[i].lda, kptr, DataParams[i].C, DataParams[i].ldc),
size);
}
}
}
}
}
return size;
}
template <typename T>
static size_t NSQ4BuSize(size_t block_size, size_t N, size_t K, bool isAsym) {
static T proB;
auto stor = proB.createStorage(static_cast<int>(N), static_cast<int>(K), static_cast<int>(block_size),
BTLA_DTYPE::S4_CLIP, BTLA_DTYPE::F32, BTLA_DTYPE::BF16, isAsym);
// TODO(Yu) support more scale dtype
return stor.mSize;
}
static bool NSQ4GemmUnPackB(float* FpData, const void* PackedBuf, size_t N, size_t K, size_t ldb, void* ThreadPool) {
auto ptr = storage::gemm::PackedWeightParser::deserialBuffer(PackedBuf);
auto uptr = std::unique_ptr<storage::gemm::IWeightBase>(ptr);
ORTThreading orth(ThreadPool);
auto N_ = static_cast<int>(N);
auto K_ = static_cast<int>(K);
auto ldb_ = static_cast<int>(ldb);
GetCPUDevice();
if (ptr) {
auto NTile = gemm::CoreAttr::get_mask_val(ptr->mCoreId, gemm::CoreAttr::NTILE_MASK, gemm::CoreAttr::NTILE_SHIFT);
auto PackRow = gemm::CoreAttr::get_packrow(ptr->mCoreId);
auto CType = gemm::CoreAttr::get_comp(ptr->mCoreId);
auto btype = static_cast<gemm::CompType>(gemm::CompTypeHelper::get_B(CType));
if (ptr->mPrologueID == BTLA_PROLOGUEB_IDS::WeightKBlockNInteger) {
auto wptr = reinterpret_cast<storage::gemm::StorageWeightKBlockNInteger*>(ptr);
auto BlkSize = wptr->mBlockSize;
if (btype == gemm::CompType::tFP32 && PackRow == 1) {
if (NTile == tAVX512F::NTILE && _cd->AVX512F() && BlkSize % tAVX512F::KTILE == 0) {
static tWeiNInt<tAVX512F, tAVX512F::ISA> proB;
proB.unpackWeight(N_, K_, wptr, FpData, ldb_, &orth);
} else if (NTile == tAVX2::NTILE && _cd->AVX2() && BlkSize % tAVX2::KTILE == 0) {
static tWeiNInt<tAVX2, tAVX2::ISA> proB;
proB.unpackWeight(N_, K_, wptr, FpData, ldb_, &orth);
}
}
if (btype == gemm::CompType::tS8 && PackRow == 4) {
if (NTile == tAMX_INT8_SS_KBlock::NTILE && _cd->AMX_INT8() && BlkSize % tAMX_INT8_SS_KBlock::KTILE == 0) {
static tWeiNInt<tAMX_INT8_SS_KBlock, tAMX_INT8_SS_KBlock::ISA> proB;
proB.unpackWeight(N_, K_, wptr, FpData, ldb_, &orth);
} else if (NTile == tAVX512_VNNI_KBlock::NTILE && _cd->AVX512_VNNI() &&
BlkSize % tAVX512_VNNI_KBlock::KTILE == 0) {
static tWeiNInt<tAVX512_VNNI_KBlock, tAVX512_VNNI_KBlock::ISA> proB;
proB.unpackWeight(N_, K_, wptr, FpData, ldb_, &orth);
} else if (NTile == tAVX_VNNI_KBlock::NTILE && _cd->AVX_VNNI() && BlkSize % tAVX_VNNI_KBlock::KTILE == 0) {
static tWeiNInt<tAVX_VNNI_KBlock, tAVX_VNNI_KBlock::ISA> proB;
proB.unpackWeight(N_, K_, wptr, FpData, ldb_, &orth);
}
}
}
return true;
}
return false;
}
template <typename T>
static void NSQ4GemmPackBImpl(void* PackedBuf, size_t BlkSize, const uint8_t* QData, const float* Scale,
const uint8_t* Zp, size_t N, size_t K, bool IsAsym, bool lastCall, size_t ldb,
void* ThreadPool) {
static T proB;
auto N_ = static_cast<int>(N);
auto K_ = static_cast<int>(K);
auto stor = proB.createStorage(N_, K_, static_cast<int>(BlkSize), BTLA_DTYPE::S4_CLIP, BTLA_DTYPE::F32,
BTLA_DTYPE::BF16, IsAsym);
stor.assign(reinterpret_cast<int8_t*>(PackedBuf));
ORTThreading orth(ThreadPool);
proB.packNbitsWeightQ4(N_, K_, IsAsym, QData, static_cast<int>(ldb), Scale, Zp, &stor, &orth);
if (lastCall) {
proB.reduceWeight(&stor, &orth);
}
}
static size_t NSQ4GemmPackBSize(size_t N, size_t K, size_t BlkSize, bool isAsym, NS_SQNBIT_COMPUTE_TYPE CompType) {
GetCPUDevice();
if (K % BlkSize != 0) {
return 0;
}
// from low precision to high precision
switch (CompType) {
case NSCompInt8:
if (!isAsym) { // asym int8 is not optimized, so fall through to others.
if (_cd->AMX_INT8() && BlkSize % tAMX_INT8_SS_KBlock::KTILE == 0) {
return NSQ4BuSize<tWeiNInt<tAMX_INT8_SS_KBlock, tAMX_INT8_SS_KBlock::ISA>>(BlkSize, N, K, isAsym);
}
if (_cd->AVX512_VNNI() && BlkSize % tAVX512_VNNI_KBlock::KTILE == 0) {
return NSQ4BuSize<tWeiNInt<tAVX512_VNNI_KBlock, tAVX512_VNNI_KBlock::ISA>>(BlkSize, N, K, isAsym);
}
if (_cd->AVX_VNNI() && BlkSize % tAVX_VNNI_KBlock::KTILE == 0) {
return NSQ4BuSize<tWeiNInt<tAVX_VNNI_KBlock, tAVX_VNNI_KBlock::ISA>>(BlkSize, N, K, isAsym);
}
}
[[fallthrough]];
case NSCompBf16:
case NSCompFp16:
case NSCompFp32:
case NSCompUndef:
if (_cd->AVX512F() && BlkSize % tAVX512F::KTILE == 0) {
return NSQ4BuSize<tWeiNInt<tAVX512F, tAVX512F::ISA>>(BlkSize, N, K, isAsym);
}
if (_cd->AVX2() && BlkSize % tAVX2::KTILE == 0) {
return NSQ4BuSize<tWeiNInt<tAVX2, tAVX2::ISA>>(BlkSize, N, K, isAsym);
}
[[fallthrough]];
default:
return 0;
}
}
static bool NSQ4GemmPackB(void* PackedBuf, const uint8_t* QData, const float* Scale, const uint8_t* Zp, size_t N,
size_t K, size_t ldb, size_t BlkSize, bool isAsym, bool lastCall,
NS_SQNBIT_COMPUTE_TYPE CompType, void* ThreadPool) {
GetCPUDevice();
// explicit statement fall through.
switch (CompType) {
case NSCompInt8:
if (!isAsym) { // asym int8 is not optimized, so fall through to others.
if (_cd->AMX_INT8() && BlkSize % tAMX_INT8_SS_KBlock::KTILE == 0) {
NSQ4GemmPackBImpl<tWeiNInt<tAMX_INT8_SS_KBlock, tAMX_INT8_SS_KBlock::ISA>>(
PackedBuf, BlkSize, QData, Scale, Zp, N, K, isAsym, lastCall, ldb, ThreadPool);
return true;
}
if (_cd->AVX512_VNNI() && BlkSize % tAVX512_VNNI_KBlock::KTILE == 0) {
NSQ4GemmPackBImpl<tWeiNInt<tAVX512_VNNI_KBlock, tAVX512_VNNI_KBlock::ISA>>(
PackedBuf, BlkSize, QData, Scale, Zp, N, K, isAsym, lastCall, ldb, ThreadPool);
return true;
}
if (_cd->AVX_VNNI() && BlkSize % tAVX_VNNI_KBlock::KTILE == 0) {
NSQ4GemmPackBImpl<tWeiNInt<tAVX_VNNI_KBlock, tAVX_VNNI_KBlock::ISA>>(PackedBuf, BlkSize, QData, Scale, Zp, N,
K, isAsym, lastCall, ldb, ThreadPool);
return true;
}
}
[[fallthrough]];
case NSCompBf16:
case NSCompFp16:
case NSCompFp32:
case NSCompUndef:
if (_cd->AVX512F() && BlkSize % tAVX512F::KTILE == 0) {
NSQ4GemmPackBImpl<tWeiNInt<tAVX512F, tAVX512F::ISA>>(PackedBuf, BlkSize, QData, Scale, Zp, N, K, isAsym,
lastCall, ldb, ThreadPool);
return true;
}
if (_cd->AVX2() && BlkSize % tAVX2::KTILE == 0) {
NSQ4GemmPackBImpl<tWeiNInt<tAVX2, tAVX2::ISA>>(PackedBuf, BlkSize, QData, Scale, Zp, N, K, isAsym, lastCall,
ldb, ThreadPool);
return true;
}
[[fallthrough]];
default:
return false;
}
}
size_t NSNBitsGemmPackBSize(size_t N, size_t K, size_t BlkSize, int nbits, bool isAsym,
NS_SQNBIT_COMPUTE_TYPE CompType) {
if (nbits == 4) {
auto jsize = NSQ4GemmPackBSize(N, K, BlkSize, isAsym, CompType);
if (jsize) {
return jsize;
}
}
return 0;
}
void NSNBitsGemmPackB(void* PackedBuf, const uint8_t* QData, const float* Scale, const uint8_t* Zp, size_t N, size_t K,
size_t ldb, size_t BlkSize, int nbits, bool isAsym, bool lastCall,
NS_SQNBIT_COMPUTE_TYPE CompType, void* ThreadPool) {
if (nbits == 4) {
if (NSQ4GemmPackB(PackedBuf, QData, Scale, Zp, N, K, ldb, BlkSize, isAsym, lastCall, CompType, ThreadPool)) {
return;
}
}
}
void NSNBitsGemmUnPackB(float* FpData, const void* PackedBuf, size_t N, size_t K, size_t ldb, void* ThreadPool) {
// only nbits=4 can be packed, so not necessary to check the nbits in DataParams
if (NSQ4GemmUnPackB(FpData, PackedBuf, N, K, ldb, ThreadPool)) {
return;
}
}
size_t NSSQNBitsGemmBatchWorkspaceSize(const size_t M, const size_t N, const size_t K, const size_t BatchN,
const NS_SQNBITS_GEMM_DATA_PACKED_PARAMS* DataParams) {
// only nbits=4 can be packed, so not necessary to check the nbits in DataParams
return NSSQ4GemmBatchWorkspaceSize(M, N, K, BatchN, DataParams);
}
void NSSQNBitsGemmBatchPackedB(const size_t M, const size_t N, const size_t K, const size_t BatchN,
const NS_SQNBITS_GEMM_DATA_PACKED_PARAMS* DataParams, void* WorkSpace,
void* ThreadPool) {
// only nbits=4 can be packed, so not necessary to check the nbits in DataParams
if (NSSQ4GemmBatchDriver(M, N, K, BatchN, DataParams, reinterpret_cast<int8_t*>(WorkSpace), ThreadPool)) {
// PackedWeight is created by bestla
return;
}
}

View file

@ -1,129 +0,0 @@
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
Module Name:
neural_speed_gemm.h
Abstract:
Prepack-weight GEMM APIs of neural_speed.
--*/
#pragma once
#include <stdint.h>
#include <cstddef>
/**
* @brief Define compute types of block quantization
*/
enum NS_SQNBIT_COMPUTE_TYPE {
NSCompUndef = 0, /*!< undef */
NSCompFp32 = 1, /*!< input fp32, accumulator fp32 */
NSCompFp16 = 2, /*!< input fp16, accumulator fp16 */
NSCompBf16 = 3, /*!< input bf16, accumulator fp32 */
NSCompInt8 = 4 /*!< input int8, accumulator int32 */
};
/**
* @brief Data parameters for NBits GEMM routine
* C = A * B
* A, C must be a float32 matrix
* B must be a packed nbits blob
* All except C are [in] parameters
*/
struct NS_SQNBITS_GEMM_DATA_PACKED_PARAMS {
const float* A = nullptr; /**< address of A (float32 matrix)*/
const void* B = nullptr; /**< address of B (packed nbits blob)*/
float* C = nullptr; /**< address of result matrix */
size_t lda = 0; /**< leading dimension of A */
size_t ldc = 0; /**< leading dimension of C*/
};
/**
* @brief Compute the byte size of the parameter combination
*
* @param N the number of columns of matrix B.
* @param K the number of rows of matrix B.
* @param block_size size of the block to quantize, elements from the same block share the same
* scale and zero point
* @param nbits number of bits used for weight quantization
* @param is_asym flag for asymmetric quantization
* @param comp_type specify input data type and accumulator data type
* @return size of the packing buffer, 0 if the operation is not yet supported.
*/
size_t NSNBitsGemmPackBSize(size_t N, size_t K, size_t block_size, int nbits, bool is_asym,
NS_SQNBIT_COMPUTE_TYPE comp_type);
/**
* @brief Prepack tensor data from n-bit quantized data, scale and zero point buffers.
*
* @param PackedBuf packed data buffer
* @param QData quantized data buffer
* @param Scale scale pointer
* @param Zp zero point pointer
* @param N the number of columns of matrix B.
* @param K the number of rows of matrix B.
* @param ldb leading dimension of B
* @param block_size size of the block to quantize, elements from the same block share the same
* scale and zero point
* @param nbits number of bits used for weight quantization (default 4)
* @param is_asym flag for asymmetric quantization
* @param comp_type specify input data type and accumulator data type
* @param last_call flag to activate the epilogue process of packB. OpKernel::PrePack will query input tensor
* one by one: QData, Scale, Zp (if is_asym is true). But kernel prefers to pack all tensors into one blob data where
* they can share the common attributes like: block_size. Meanwhile, kernel has some pre-computations to speed up
* inference which require that all blob data are ready. So, you need to set this flag to true when passing Scale
* (is_asym is false) and Zp(is_asym is true).
* @param thread_pool
*/
void NSNBitsGemmPackB(void* PackedBuf, const uint8_t* QData, const float* Scale, const uint8_t* Zp, size_t N, size_t K,
size_t ldb, size_t block_size, int nbits, bool is_asym, bool last_call,
NS_SQNBIT_COMPUTE_TYPE comp_type, void* thread_pool);
/**
* @brief Unpack and dequantize to fp32
*
* @param FpData unpacked float32 data
* @param PackedBuf quantized and packed data
* @param N the number of columns of matrix B.
* @param K the number of rows of matrix B.
* @param ldb leading dimension of B
* @param thread_pool
*/
void NSNBitsGemmUnPackB(float* FpData, const void* PackedBuf, size_t N, size_t K, size_t ldb, void* thread_pool);
/**
* @brief Get the workspace size required by computation.
*
* @param[in] M row size of matrix A and C
* @param[in] N column size of matrix B and C
* @param[in] K column size of matrix A and row size of matrix B
* @param[in] BatchN number of batches
* @param[inout] DataParams An array (size BatchN) of parameter blocks
* @return Workspace size in bytes
*/
size_t NSSQNBitsGemmBatchWorkspaceSize(const size_t M, const size_t N, const size_t K, const size_t BatchN,
const NS_SQNBITS_GEMM_DATA_PACKED_PARAMS* DataParams);
/**
* @brief Batched GEMM: C = A * B
* A, C must be a float32 matrix
* B must be a packed nbits blob
*
* @param[in] M row size of matrix A and C
* @param[in] N column size of matrix B and C
* @param[in] K column size of matrix A and row size of matrix B
* @param[in] BatchN number of batches
* @param[inout] DataParams An array (size BatchN) of parameter blocks
* @param[in] WorkSpace temporary buffer
* @param[in] ThreadPool
* @return
*/
void NSSQNBitsGemmBatchPackedB(const size_t M, const size_t N, const size_t K, const size_t BatchN,
const NS_SQNBITS_GEMM_DATA_PACKED_PARAMS* DataParams, void* WorkSpace,
void* ThreadPool = nullptr);

View file

@ -1,40 +0,0 @@
//-----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
//-----------------------------------------------------------------------------
#pragma once
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-value"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wuninitialized"
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4457)
#pragma warning(disable : 4189)
#pragma warning(disable : 4100)
#pragma warning(disable : 4244)
#pragma warning(disable : 4267)
#pragma warning(disable : 4702)
#pragma warning(disable : 4127)
#endif
#include "bestla/bestla_prologue_a.h"
#include "bestla/bestla_wrapper.h"
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif

View file

@ -385,9 +385,7 @@ InlinedVector<std::unique_ptr<GraphTransformer>> GenerateTransformers(
}
#endif
#if !defined(ORT_NEURAL_SPEED)
transformers.emplace_back(std::make_unique<MatMulNBitsFusion>(cpu_ep));
#endif // !defined(ORT_NEURAL_SPEED)
#endif // !defined(DISABLE_CONTRIB_OPS)
// The QDQFinalCleanupTransformer must run AFTER other transformers that fuse Q/DQ nodes. Otherwise, their
@ -469,9 +467,7 @@ InlinedVector<std::unique_ptr<GraphTransformer>> GenerateTransformersForMinimalB
}
transformers.emplace_back(std::make_unique<ConvActivationFusion>(cpu_ep, apply_context));
#if !defined(ORT_NEURAL_SPEED)
transformers.emplace_back(std::make_unique<MatMulNBitsFusion>(cpu_ep, apply_context));
#endif // !defined(ORT_NEURAL_SPEED)
#else // !defined(DISABLE_CONTRIB_OPS)
ORT_UNUSED_PARAMETER(apply_context);
#endif // !defined(DISABLE_CONTRIB_OPS)

View file

@ -293,7 +293,7 @@ void TestMatMulNBitsTyped() {
RunTest<AType>(opts);
}
#if !defined(ORT_NEURAL_SPEED) && !defined(USE_DML)
#if !defined(USE_DML)
{
TestOptions opts = base_opts;
opts.has_g_idx = true;
@ -324,7 +324,7 @@ void TestMatMulNBitsTyped() {
opts.has_zero_point = true, opts.zp_is_4bit = false;
RunTest<AType>(opts);
}
#endif // !defined(ORT_NEURAL_SPEED) && !defined(USE_DML)
#endif // !defined(USE_DML)
{
TestOptions opts = base_opts;
@ -349,7 +349,7 @@ TEST(MatMulNBits, Float32) {
}
#ifdef MLAS_TARGET_AMD64_IX86
#if !defined(ORT_NEURAL_SPEED) && !defined(USE_DML)
#if !defined(USE_DML)
// Actual and expected difference is over 0.01 with DmlExecutionProvider.
// Skip the tests instead of raising the tolerance to make is pass.
TEST(MatMulNBits, Float16) {
@ -451,177 +451,6 @@ TEST(MatMulNBits, Float16Large) {
}
#endif // defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_DML)
#if defined(ORT_NEURAL_SPEED)
namespace {
void RunSharedPrepackedWeightsTest(int64_t M, int64_t N, int64_t K, int block_size, bool is_asym,
int64_t acc_lvl) {
// (M x K) X (K x N)
OpTester test("MatMulNBits", 1, kMSDomain);
test.AddAttribute<int64_t>("accuracy_level", acc_lvl);
test.AddAttribute<int64_t>("block_size", int64_t(block_size));
test.AddAttribute<int64_t>("bits", QBits);
test.AddAttribute<int64_t>("N", N);
test.AddAttribute<int64_t>("K", K);
std::vector<float> input0_vals(M * K);
float fv = -135.f;
for (auto& f : input0_vals) {
f = fv / 127;
fv++;
if (fv > 135.f) {
fv = -135.f;
}
}
size_t kblks = K / block_size;
std::vector<uint8_t> input1_vals(N * K / 2);
for (size_t i = 0; i < input1_vals.size(); i++) {
input1_vals[i] = uint8_t(i);
}
std::vector<float> input2_vals(N * kblks, 0.002f);
for (size_t i = 0; i < N * kblks; i++) {
input2_vals[i] += (i % 100) * 0.00003f;
}
std::vector<uint8_t> input3_vals(N * kblks / 2, static_cast<uint8_t>(0x88));
std::vector<float> input1_f_vals(N * K);
if (is_asym) {
for (size_t i = 0; i < N * kblks; i += 2) {
input3_vals[i / 2] = static_cast<uint8_t>(i + 1);
}
for (int64_t i = 0; i < K; i += 2) {
for (int64_t j = 0; j < N; j++) {
auto srcv = input1_vals[j * K / 2 + i / 2];
auto koff = i % (block_size * 2);
auto zpv = input3_vals[j * kblks / 2 + i / block_size / 2];
auto zp0 = koff < block_size ? (zpv & 0xf) - 8 : ((zpv & 0xf0) >> 4) - 8;
auto src0 = (srcv & 0xf) - 8;
auto src1 = ((srcv & 0xf0) >> 4) - 8;
auto scale0 = input2_vals[j * kblks + i / block_size];
auto scale1 = input2_vals[j * kblks + (i + 1) / block_size];
input1_f_vals[i * N + j] = (static_cast<float>(src0) - zp0) * scale0;
input1_f_vals[(i + 1) * N + j] = (static_cast<float>(src1) - zp0) * scale1;
}
}
} else {
for (int64_t i = 0; i < K; i += 2) {
for (int64_t j = 0; j < N; j++) {
auto srcv = input1_vals[j * K / 2 + i / 2];
auto src0 = (srcv & 0xf) - 8;
auto src1 = ((srcv & 0xf0) >> 4) - 8;
auto scale0 = input2_vals[j * kblks + i / block_size];
auto scale1 = input2_vals[j * kblks + (i + 1) / block_size];
input1_f_vals[i * N + j] = static_cast<float>(src0) * scale0;
input1_f_vals[(i + 1) * N + j] = static_cast<float>(src1) * scale1;
}
}
}
std::vector<float> expected_vals(M * N);
for (int64_t m = 0; m < M; m++) {
for (int64_t n = 0; n < N; n++) {
float sum = 0.0f;
for (int64_t k = 0; k < K; k++) {
sum += input0_vals[m * K + k] * input1_f_vals[k * N + n];
}
expected_vals[m * N + n] = sum;
}
}
test.AddInput<float>("A", {M, K}, input0_vals, false);
test.AddInput<uint8_t>("B", {N, static_cast<int64_t>(kblks), static_cast<int64_t>(block_size / 2)}, input1_vals,
true);
test.AddInput<float>("scales", {N, static_cast<int64_t>(kblks)}, input2_vals, true);
if (is_asym) {
test.AddInput<uint8_t>("zero_points", {N, static_cast<int64_t>(kblks / 2)}, input3_vals, true);
}
test.AddOutput<float>("Y", {M, N}, expected_vals, false);
if (acc_lvl == 4) {
test.SetOutputAbsErr("Y", 0.1f);
}
OrtValue b, scale, zp;
Tensor::InitOrtValue(DataTypeImpl::GetType<uint8_t>(),
TensorShape({N, static_cast<int64_t>(kblks), static_cast<int64_t>(block_size / 2)}),
input1_vals.data(), OrtMemoryInfo(CPU, OrtAllocatorType::OrtDeviceAllocator), b);
Tensor::InitOrtValue(DataTypeImpl::GetType<float>(), TensorShape({N, static_cast<int64_t>(kblks)}),
input2_vals.data(), OrtMemoryInfo(CPU, OrtAllocatorType::OrtDeviceAllocator), scale);
if (is_asym) {
Tensor::InitOrtValue(DataTypeImpl::GetType<uint8_t>(), TensorShape({N, static_cast<int64_t>(kblks / 2)}),
input3_vals.data(), OrtMemoryInfo(CPU, OrtAllocatorType::OrtDeviceAllocator), zp);
}
SessionOptions so;
// Set up B as a shared initializer to be shared between sessions
ASSERT_EQ(so.AddInitializer("B", &b), Status::OK());
ASSERT_EQ(so.AddInitializer("scales", &scale), Status::OK());
if (is_asym) {
ASSERT_EQ(so.AddInitializer("zero_points", &zp), Status::OK());
}
// We want all sessions running using this OpTester to be able to share pre-packed weights if applicable
test.EnableSharingOfPrePackedWeightsAcrossSessions();
// Pre-packing is limited just to the CPU EP for now and we will only test the CPU EP
// and we want to ensure that it is available in this build
auto cpu_ep = []() -> std::vector<std::unique_ptr<IExecutionProvider>> {
std::vector<std::unique_ptr<IExecutionProvider>> execution_providers;
execution_providers.push_back(DefaultCpuExecutionProvider());
return execution_providers;
};
size_t number_of_pre_packed_weights_counter_session_1 = 0;
size_t number_of_shared_pre_packed_weights_counter = 0;
// Session 1
{
auto ep_vec = cpu_ep();
test.Run(so, OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &ep_vec, {},
&number_of_pre_packed_weights_counter_session_1, &number_of_shared_pre_packed_weights_counter);
// Assert that no pre-packed weights have been shared thus far
ASSERT_EQ(number_of_shared_pre_packed_weights_counter, static_cast<size_t>(0));
}
auto number_of_elements_in_shared_prepacked_buffers_container = test.GetNumPrePackedWeightsShared();
// Assert that the number of elements in the shared container
// is the same as the number of weights that have been pre-packed
ASSERT_EQ(number_of_pre_packed_weights_counter_session_1, number_of_elements_in_shared_prepacked_buffers_container);
// On some platforms/architectures MLAS may choose to not do any pre-packing and the number of elements
// that have been pre-packed will be zero in which case we do not continue with the testing
// of "sharing" of pre-packed weights as there are no pre-packed weights to be shared at all.
if (number_of_pre_packed_weights_counter_session_1 == 0) return;
// Session 2
{
size_t number_of_pre_packed_weights_counter_session_2 = 0;
auto ep_vec = cpu_ep();
test.Run(so, OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &ep_vec, {},
&number_of_pre_packed_weights_counter_session_2, &number_of_shared_pre_packed_weights_counter);
// Assert that the same number of weights were pre-packed in both sessions
ASSERT_EQ(number_of_pre_packed_weights_counter_session_1, number_of_pre_packed_weights_counter_session_2);
// Assert that the number of pre-packed weights that were shared equals
// the number of pre-packed weights in the second session
ASSERT_EQ(number_of_pre_packed_weights_counter_session_2,
static_cast<size_t>(number_of_shared_pre_packed_weights_counter));
}
}
} // namespace
TEST(MatMulNBits, SharedPrepackedWeights) {
RunSharedPrepackedWeightsTest(2, 4096, 4096, 32, true, 1);
RunSharedPrepackedWeightsTest(2, 4096, 4096, 32, false, 1);
RunSharedPrepackedWeightsTest(2, 4096, 4096, 128, false, 1);
RunSharedPrepackedWeightsTest(2, 4096, 4096, 128, false, 4);
RunSharedPrepackedWeightsTest(2, 4096, 4096, 1024, false, 4);
RunSharedPrepackedWeightsTest(2, 4096, 4096, 4096, false, 4);
}
#endif // defined(ORT_NEURAL_SPEED)
} // namespace test
} // namespace onnxruntime

View file

@ -119,8 +119,8 @@ static void SQNBitGemmArgs(benchmark::internal::Benchmark* b) {
b->ArgNames({"BlkLen", "M", "N", "K", "Threads", "Symmetric", "HasBias", "ComputeType"});
b->ArgsProduct({
{16, 32, 64, 128, 256}, // BlkLen
{1, 1024, 2048}, // M
{128}, // BlkLen
{1}, // M
{4096, 11008}, // N
{4096, 11008}, // K
{1, 8}, // Threads

View file

@ -318,7 +318,6 @@ TEST(GraphRuntimeOptimizationTest, ConvActivation) {
});
}
#if !defined(ORT_NEURAL_SPEED)
TEST(GraphRuntimeOptimizationTest, FuseMatMulNBitsAndAdd) {
SaveAndLoadRuntimeOptimizationsForModel(
ORT_TSTR("testdata/transform/runtime_optimization/matmulnbits_add.onnx"),
@ -332,7 +331,6 @@ TEST(GraphRuntimeOptimizationTest, FuseMatMulNBitsAndAdd) {
(OpCountMap{{"com.microsoft.MatMulNBits", 1}}));
});
}
#endif // !defined(ORT_NEURAL_SPEED)
TEST(GraphRuntimeOptimizationTest, TestNhwcTransformer) {
CheckNhwcTransformerIsApplied(

View file

@ -312,25 +312,6 @@ stages:
EnablePython: false
MachinePool: 'onnxruntime-Win-CPU-2022'
- stage: NeuralSpeed
dependsOn: [ ]
jobs:
- template: templates/jobs/win-ci-vs-2022-job.yml
parameters:
BuildConfig: 'RelWithDebInfo'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --cmake_extra_defines onnxruntime_USE_NEURAL_SPEED=ON
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_neural_speed
RunOnnxRuntimeTests: true
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'onnxruntime-Win-CPU-2022'
#Generate test coverage report and publish the data to a Cloud database. Only runs daily.
- stage: CodeCoverage
dependsOn: [ ]