in src/transformer_op.cc [311:362]
void Compute(OpKernelContext* ctx) override {
const Tensor& dy = ctx->input(0);
const Tensor& y = ctx->input(1);
const Tensor& s = ctx->input(2);
OpInputList m; ctx->input_list("mask", &m);
// y: D0, D1, D2, D3
// m: 1, D1, D2, D3
// m: 1, 1, D2, D3
// m: 1, 1, 1, D3
int rank = y.dims();
uint D3 = y.dim_size(--rank);
uint D2 = 1, D1 = 1, D0 = 1, M2 = 0, M1 = 0;
const float* m_ptr = NULL;
if (m.size() > 0)
{
// gather inner dimensions and strides of the mask
// only dims 1 and 2 are unknown for the mask, so just deterimine those strides
if (rank > 0) { D2 = y.dim_size(--rank); M2 = m[0].dim_size(rank) == 1 ? 0 : D3; }
if (rank > 0) { D1 = y.dim_size(--rank); M1 = m[0].dim_size(rank) == 1 ? 0 : D3*D2; }
m_ptr = m[0].flat<float>().data();
}
while (rank > 0) { D0 *= y.dim_size(--rank); }
OP_REQUIRES(ctx, D2 < 65536, errors::Internal("D2 < 65536: ", D2));
OP_REQUIRES(ctx, D1 < 65536, errors::Internal("D1 < 65536: ", D1));
Tensor* dx = NULL;
OP_REQUIRES_OK(ctx, ctx->allocate_output(0, dy.shape(), &dx));
V* dx_ptr = ( V*)dx->flat<T>().data();
const V* dy_ptr = (const V*)dy.flat<T>().data();
const V* y_ptr = (const V*)y.flat<T>().data();
CUstream stream = ((CUDAStream*)ctx->op_device_context()->stream()->implementation())->cuda_stream();
Benchmark* bench = nullptr;
if (bench_)
{
char bench_string[256];
sprintf(bench_string, "MaskedSoftmaxGrad (%6d,%4d,%4d,%4d) %d, %d", D0, D1, D2, D3, (uint)m.size(), (uint)sizeof(V));
bench = new Benchmark(stream, bench_string, dy.NumElements()*3*sizeof(V), 0, bench_);
}
int repeat = bench_ ? bench_ : 1;
for (int i = 0; i < repeat; i++)
MaskedSoftmaxGrad<V>(stream, dx_ptr, dy_ptr, y_ptr, m_ptr, D0, D1, D2, D3, M1, M2, s.scalar<float>()());
if (bench) delete bench;
}