#ifndef GPU_INTEL_RNN_CELL_COMPUTE_H
#define GPU_INTEL_RNN_CELL_COMPUTE_H
#include "gpu/intel/include/conversion.h"
#include "gpu/intel/rnn/common.h"
#if CELL_COMP_ENABLED
#define DHC_TG get_local_size(0)
#define DHC_LOCAL (CELL_DHC_THR * DHC_TG)
#define BATCH_TG get_local_size(1)
#define BATCH_LOCAL (CELL_BATCH_THR * BATCH_TG)
#define M_THR_BLOCK CELL_BATCH_THR
#define N_THR_BLOCK CELL_DHC_THR
#define N_OUTER_BLOCK n_gates
#define K_TG_BLOCK SUBGROUP_SIZE
#define K_THR_BLOCK 1
const int gemm_k_block = SUBGROUP_SIZE;
typedef int64_t cell_offset_t;
typedef int64_t grid_offset_t;
typedef dim_t cell_dim_t;
typedef struct {
cell_dim_t m;
cell_dim_t k;
cell_dim_t n_inner;
cell_dim_t n_outer;
} gemm_dims_t;
typedef struct {
bool m;
bool k;
bool n;
} gemm_overflow_t;
typedef struct {
cell_offset_t mb;
cell_offset_t slc;
cell_offset_t sic;
} cell_strides_t;
typedef struct {
grid_offset_t iter;
cell_strides_t cell;
} grid_strides_t;
typedef struct {
__global const WEI_LAYER_DATA_T *ptr;
cell_strides_t strides;
} const_wei_layer_cell_t;
typedef struct {
__global const WEI_ITER_DATA_T *ptr;
cell_strides_t strides;
} const_wei_iter_cell_t;
typedef struct {
__global AUX_DATA_T *ptr;
cell_strides_t strides;
} aux_cell_t;
typedef struct {
__global const AUX_DATA_T *ptr;
cell_strides_t strides;
} const_aux_cell_t;
typedef struct {
__global WS_STATE_DATA_T *ptr;
cell_strides_t strides;
} ws_state_cell_t;
typedef struct {
__global const WS_STATE_DATA_T *ptr;
cell_strides_t strides;
} const_ws_state_cell_t;
typedef struct {
cell_dim_t mb;
cell_dim_t dhc;
cell_dim_t slc;
cell_dim_t sic;
} cell_dims_t;
typedef struct {
union {
struct {
float alpha;
__global BIAS_DATA_T *bias;
__global float *tm_scales;
} rnn;
struct {
__global AUX_DATA_T *c_states;
__global const AUX_DATA_T *c_states_iter;
__global BIAS_DATA_T *bias;
__global float *tm_scales;
float tm_cscale;
} lstm;
struct {
__global WS_STATE_DATA_T *hidden_state_iter;
__global AUX_DATA_T *grid;
__global BIAS_DATA_T *bias;
__global float *tm_scales;
} lbr_gru;
};
} cell_ctx_t;
typedef struct {
cell_dim_t mb;
cell_dim_t dhc;
} cell_loops_t;
#define NEED_SCRATCH_GATES \
(!(CELL_COMPUTE_GEMM_LAYER && CELL_COMPUTE_GEMM_ITER))
typedef enum {
copy_none = 0,
copy_gemm_layer = 1,
copy_gemm_iter = 2,
copy_all = 3
} copy_scratch_memory;
inline int checkCopyScratchMemory(
bool cell_compute_gemm_layer, bool cell_compute_gemm_iter) {
if (!cell_compute_gemm_layer & cell_compute_gemm_iter) {
return copy_gemm_layer;
}
if (cell_compute_gemm_layer & !cell_compute_gemm_iter) {
return copy_gemm_iter;
}
if (!cell_compute_gemm_layer & !cell_compute_gemm_iter) { return copy_all; }
return copy_none;
}
inline void __attribute__((overloadable)) load(
float *s, const __global float *data, bool is_valid) {
*s = is_valid ? data[get_sub_group_local_id()] : 0;
}
inline void __attribute__((overloadable)) load(
float *s, const __global half *data, bool is_valid) {
*s = is_valid ? into_float(data[get_sub_group_local_id()]) : 0;
}
inline void __attribute__((overloadable)) load(
float *s, const __global ushort *data, bool is_valid) {
*s = is_valid ? into_float(as_bf16(data[get_sub_group_local_id()])) : 0;
}
inline float __attribute__((overloadable)) sg_get(float s, int offset) {
return intel_sub_group_shuffle(s, offset);
}
inline bool __attribute__((overloadable)) sg_get(
bool s[gemm_k_block / SUBGROUP_SIZE], int offset) {
return intel_sub_group_shuffle(
s[offset / SUBGROUP_SIZE], offset % SUBGROUP_SIZE);
}
#endif
#endif