void Compute()

in src/layer_norm_op.cc [227:304]


  void Compute(OpKernelContext* ctx) override
  {
    const Tensor& dy = ctx->input(0);
    const Tensor& x  = ctx->input(1);
    const Tensor& g  = ctx->input(2);
    const Tensor& b  = ctx->input(3);
    const Tensor& mean = ctx->input(4);
    const Tensor& rstd = ctx->input(5);

    if (axis_ < 0)
      axis_ += x.dims();

    int rank = x.dims();
    int N = 1, K = x.dim_size(axis_);
    for (int i = 0; i < rank; i++)
      if (i != axis_)
        N *= x.dim_size(i);

    if (K_ == 0)
    {
      K_    = K / S_;
      rcpK_ = 1.0f / (float)K_;
      SMs_  = GetCountSMs();
    }

    Tensor* dx = nullptr;
    Tensor* dg = nullptr;
    Tensor* db = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, x.shape(), &dx));
    OP_REQUIRES_OK(ctx, ctx->allocate_output(1, g.shape(), &dg));
    OP_REQUIRES_OK(ctx, ctx->allocate_output(2, b.shape(), &db));

    Tensor* P1 = nullptr;
    Tensor* P2 = nullptr;
    TensorShape shapeP;
    if (axis_ == 0)
    {
      shapeP.AddDim(SMs_*2);
      shapeP.AddDim(N);
    }
    OP_REQUIRES_OK(ctx, ctx->allocate_output(3,  shapeP, &P1));
    OP_REQUIRES_OK(ctx, ctx->allocate_output(4,  shapeP, &P2));
    float* p1_ptr = nullptr;
    float* p2_ptr = nullptr;
    if (axis_ == 0)
    {
      p1_ptr = P1->flat<float>().data();
      p2_ptr = P2->flat<float>().data();
    }

             V1*   dx_ptr = (V1*)dx->flat<T>().data();
          float*   dg_ptr = dg->flat<float>().data();
          float*   db_ptr = db->flat<float>().data();
    const    V1*   dy_ptr = (const V1*)dy.flat<T>().data();
    const    V1*    x_ptr = (const V1*)x.flat<T>().data();
    const float*    g_ptr = g.flat<float>().data();
    const float*    b_ptr = b.flat<float>().data();
    const float* mean_ptr = mean.flat<float>().data();
    const float* rstd_ptr = rstd.flat<float>().data();

    CUstream stream = ((CUDAStream*)ctx->op_device_context()->stream()->implementation())->cuda_stream();

    Benchmark* bench = nullptr;
    if (bench_) bench = new Benchmark(stream, "LayerNormBackward", N*S_*K_*5*sizeof(T), 0, repeat_);

    for (int r = 0; r < repeat_; r++)
      if (axis_ == 0)
        LayerNormBackward_CN<V1,V4>(stream, SMs_, dx_ptr, dg_ptr, db_ptr, p1_ptr, p2_ptr, dy_ptr, x_ptr, g_ptr, b_ptr, mean_ptr, rstd_ptr, epsilon_, K_, N, rcpK_, relu_);
      else
      {
        if (S_ > 1 || K_ <= 1024*8)
          LayerNormSegmentedBackward_NC<V1,V4>(stream, SMs_, dx_ptr, dg_ptr, db_ptr, dy_ptr, x_ptr, g_ptr, b_ptr, mean_ptr, rstd_ptr, epsilon_, N, S_, K_, rcpK_, relu_, atomics_);
        else
          LayerNormBackward_NC<V1,V4>(stream, SMs_, dx_ptr, dg_ptr, db_ptr, dy_ptr, x_ptr, g_ptr, b_ptr, mean_ptr, rstd_ptr, epsilon_, K_, N, rcpK_, relu_);
      }

    if (bench) delete bench;
  }