#ifndef CPU_X64_GEMM_GEMM_INFO_HPP
#define CPU_X64_GEMM_GEMM_INFO_HPP
#include <cstdint>
#include <memory>
#include "common/c_types_map.hpp"
#include "cpu/x64/gemm/gemm_pack_storage.hpp"
#include "cpu/x64/gemm/gemm_threading.hpp"
namespace dnnl {
namespace impl {
namespace cpu {
namespace x64 {
enum class pack_type { none, pack_a, pack_b };
enum class offset_type {
none,
fixed,
column,
row,
};
enum { no_sum = 0, do_sum = 1 };
enum { no_trans = 0, do_trans = 1, packed = 2 };
enum { no_beta0 = 0, do_beta0 = 1 };
enum { no_alpha1 = 0, do_alpha1 = 1 };
template <typename a_t, typename b_t, typename c_t>
struct gemm_info_t {
int transa, transb;
offset_type offsetc;
dim_t m, n, k;
dim_t lda, ldb, ldc;
const a_t *a;
const b_t *b;
c_t *c;
float alpha, beta;
int32_t ao;
int32_t bo;
const c_t *co;
pack_type packing;
gemm_pack_storage_t *pack_dst;
bool measure_only;
std::shared_ptr<const gemm_pack_storage_t> a_packed, b_packed;
dim_t um {}, un {}, uk {}, bm {}, bn {}, bk {};
dim_t bn_small_k {}, bk_traditional {}, blocking_small_k {};
int swap = false;
using copy_a_fptr_t = void (*)(const dim_t *m, const dim_t *n,
const a_t *src, const dim_t *ldsrc, const float *alpha, a_t *dst,
const dim_t *dummy1, const dim_t *dummy2, c_t *row_col_sum);
using copy_b_fptr_t = void (*)(const dim_t *m, const dim_t *n,
const b_t *src, const dim_t *ldsrc, const float *alpha, b_t *dst,
const dim_t *dummy1, const dim_t *dummy2, c_t *row_col_sum);
using gemm_fptr_t = void (*)(const dim_t *, const dim_t *, const dim_t *,
const float *, const a_t *, const b_t *, c_t *, const dim_t,
const c_t *, const c_t *);
using gemv_fptr_t = void (*)(const dim_t *, const dim_t *, const float *,
const a_t *, const dim_t *, const b_t *, const dim_t *, c_t *,
const dim_t *);
using gemv_s8s8s32_fptr_t
= void (*)(const dim_t, const dim_t, const float, const int8_t *,
const dim_t, const int8_t *, const float, int32_t *);
using gemv_s8u8s32_fptr_t
= void (*)(const dim_t, const dim_t, const float, const int8_t *,
const dim_t, const uint8_t *, const float, int32_t *);
using gemv_u8s8s32_fptr_t
= void (*)(const dim_t, const dim_t, const float, const uint8_t *,
const dim_t, const int8_t *, const float, int32_t *);
copy_a_fptr_t copyA = nullptr;
copy_b_fptr_t copyB = nullptr;
gemm_fptr_t kernel[2][2][2] = {{{nullptr}}};
gemv_fptr_t gemv_kernel[2] = {nullptr};
gemv_s8s8s32_fptr_t gemv_s8s8s32_kernel = nullptr;
gemv_s8u8s32_fptr_t gemv_s8u8s32_kernel = nullptr;
gemv_u8s8s32_fptr_t gemv_u8s8s32_kernel = nullptr;
static copy_a_fptr_t copy_a_kern[2][2];
static copy_b_fptr_t copy_b_kern[2][2];
static gemm_fptr_t kern[2][2][2][2];
static gemv_fptr_t gemv_kern[2];
static gemv_s8s8s32_fptr_t gemv_s8s8s32_kern;
static gemv_s8u8s32_fptr_t gemv_s8u8s32_kern;
static gemv_u8s8s32_fptr_t gemv_u8s8s32_kern;
template <bool is_trans>
static void copy_a_sum_ref(const dim_t *p_k, const dim_t *p_m,
const a_t *src, const dim_t *p_ld, const float *p_alpha, a_t *dst,
const dim_t *dummy1, const dim_t *dummy2, c_t *a_row_sum) {
copy_a_kern[is_trans][no_sum](
p_k, p_m, src, p_ld, p_alpha, dst, dummy1, dummy2, a_row_sum);
dim_t k = *p_k;
dim_t m = *p_m;
dim_t ld = *p_ld;
if (!is_trans) {
PRAGMA_OMP_SIMD()
for (dim_t i = 0; i < m; i++)
a_row_sum[i] = 0;
for (dim_t j = 0; j < k; j++) {
PRAGMA_OMP_SIMD()
for (dim_t i = 0; i < m; i++) {
a_row_sum[i] += src[i + j * ld];
}
}
} else {
for (dim_t i = 0; i < m; i++) {
c_t acc = 0;
PRAGMA_OMP_SIMD(reduction(+ : acc))
for (dim_t j = 0; j < k; j++) {
acc += src[j + i * ld];
}
a_row_sum[i] = acc;
}
}
}
template <bool is_trans>
static void copy_b_sum_ref(const dim_t *p_k, const dim_t *p_n,
const b_t *src, const dim_t *p_ld, const float *alpha, b_t *dst,
const dim_t *dummy1, const dim_t *dummy2, c_t *b_col_sum) {
copy_b_kern[is_trans][no_sum](
p_k, p_n, src, p_ld, alpha, dst, dummy1, dummy2, b_col_sum);
dim_t k = *p_k;
dim_t n = *p_n;
dim_t ld = *p_ld;
if (!is_trans) {
for (dim_t j = 0; j < n; j++) {
c_t acc = 0;
PRAGMA_OMP_SIMD(reduction(+ : acc))
for (dim_t i = 0; i < k; i++)
acc += src[i + j * ld];
b_col_sum[j] = acc;
}
} else {
PRAGMA_OMP_SIMD()
for (dim_t j = 0; j < n; j++)
b_col_sum[j] = 0;
for (dim_t i = 0; i < k; i++) {
PRAGMA_OMP_SIMD()
for (dim_t j = 0; j < n; j++)
b_col_sum[j] += src[j + i * ld];
}
}
}
bool force_nocopy;
gemm_info_t(const char *transA, const char *transB, const char *offsetC,
const dim_t *m, const dim_t *n, const dim_t *k, const float *alpha,
const a_t *a, const dim_t *lda, const a_t *oa, const b_t *b,
const dim_t *ldb, const b_t *ob, const float *beta, c_t *c,
const dim_t *ldc, const c_t *oc, bool force_nocopy,
pack_type packing, gemm_pack_storage_t *pack_dst,
bool measure_only);
bool hasKernels(void);
void update_blocking(const gemm_threading_t &thread_info);
private:
void jit_init(void);
};
} } } }
#endif