in src/bst_op.cc [251:320]
void Compute_XN(OpKernelContext* ctx, uint op, uint max_lut)
{
const Tensor& a = ctx->input(0);
const Tensor& b = ctx->input(1);
const Tensor& lut = ctx->input(2 + op);
OP_REQUIRES(ctx, a.dims() == 5 && b.dims() == 3, errors::InvalidArgument("Mismatched Shapes: a,b"));
OP_REQUIRES(ctx, lut.dims() == 3, errors::InvalidArgument("Bad lut"));
uint lut_heads = lut.dim_size(0);
uint lut_dim = lut.dim_size(1);
uint batch_dim = b.dim_size(0);
uint state_dim = b.dim_size(2);
if (head_state_ == 0)
{
OP_REQUIRES(ctx,
a.dim_size(0) == batch_dim &&
a.dim_size(1) == heads_ &&
a.dim_size(2) == blocks_ &&
a.dim_size(3) == blk_size_ &&
a.dim_size(4) == blk_size_, errors::InvalidArgument("Mismatched A shape"));
head_state_ = state_dim / heads_;
OP_REQUIRES(ctx, state_dim % heads_ == 0, errors::InvalidArgument("state_dim not evenly divisible by number of heads"));
OP_REQUIRES(ctx, (head_state_ & 7) == 0, errors::InvalidArgument("Head state dim must be multiple of 8, and ideally a multiple of 64"));
OP_REQUIRES(ctx, b.dim_size(1) == ctx_blks_b_ * blk_size_, errors::InvalidArgument("Bad B context length"));
OP_REQUIRES(ctx, lut_heads == heads_ || lut_heads == 1, errors::InvalidArgument("Bad head dim"));
uint div = CEIL_DIV(head_state_, 64);
magicu64(div, magic_, shift_);
OP_REQUIRES(ctx, magic_ > 0, errors::InvalidArgument("Bad magic for div: ", div));
}
Tensor* c;
TensorShape shapeC({batch_dim, ctx_blks_c_ * blk_size_, state_dim});
OP_REQUIRES_OK(ctx, ctx->allocate_output(0, shapeC, &c));
const uint2* l_ptr = (const uint2*)lut.flat<int32>().data();
CUstream stream = ((CUDAStream*)ctx->op_device_context()->stream()->implementation())->cuda_stream();
Benchmark* bench = nullptr;
if (bench_) bench = new Benchmark(stream, bench_string_, 0, flops_ * (float)(batch_dim * state_dim), repeat_);
if (a.dtype() == DT_HALF)
{
OP_REQUIRES(ctx, major_ >= 7, errors::InvalidArgument("Tensorcore GPU required"));
const ehalf* a_ptr = (const ehalf*)a.tensor_data().data();
const ehalf* b_ptr = (const ehalf*)b.tensor_data().data();
ehalf* c_ptr = ( ehalf*)c->tensor_data().data();
for (int r = 0; r < repeat_; r++)
bst_hgemm_xn(stream, l_ptr, a_ptr, b_ptr, c_ptr, blk_size_, blocks_, batch_dim, ctx_blks_b_, ctx_blks_c_, heads_, head_state_, lut_heads, lut_dim, op, magic_, shift_, max_lut);
}
else
{
const bhalf* a_ptr = (const bhalf*)a.tensor_data().data();
const float* b_ptr = (const float*)b.tensor_data().data();
float* c_ptr = ( float*)c->tensor_data().data();
OP_REQUIRES(ctx, blk_size_ == 32, errors::InvalidArgument("Only blocksize=32 supported for fp32 pathway."));
for (int r = 0; r < repeat_; r++)
bst_sgemm_xn(stream, l_ptr, a_ptr, b_ptr, c_ptr, blk_size_, blocks_, batch_dim, ctx_blks_b_, ctx_blks_c_, heads_, head_state_, lut_heads, lut_dim, op, magic_, shift_, max_lut);
}
if (bench) delete bench;
}