void Compute()

in src/layer_norm_op.cc [89:170]


  void Compute(OpKernelContext* ctx) override
  {
    const Tensor& x = ctx->input(0);
    const Tensor& g = ctx->input(1);
    const Tensor& b = ctx->input(2);

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

    int N = 1, K = x.dim_size(axis_), last_dim = x.dims()-1;
    TensorShape shapeN;
    shapeN.AddDim(S_);
    for (int i = 0; i <= last_dim; i++)
    {
      if (i != axis_)
      {
        shapeN.AddDim(x.dim_size(i));
        N *= x.dim_size(i);
      }
    }
    OP_REQUIRES(ctx, axis_ != 0 || (N & 3) == 0, errors::InvalidArgument("Sum of non-feature axis dims needs to be multiple of 4 for feature axis=0."));

    if (K_ == 0)
    {
      OP_REQUIRES(ctx, K == g.shape().num_elements(), errors::InvalidArgument("Bad Gain Shape"));
      OP_REQUIRES(ctx, K == b.shape().num_elements(), errors::InvalidArgument("Bad Bias Shape"));
      OP_REQUIRES(ctx, (K % S_) == 0, errors::InvalidArgument("Shape not evenly devided by segments"));
      OP_REQUIRES(ctx, axis_ != 0 || S_ == 1, errors::InvalidArgument("Segments only implemented on axis=1 for now"));
      K_    = K / S_;
      rcpK_ = 1.0f / (float)K_;
      SMs_  = GetCountSMs();
    }

    Tensor*    y = nullptr;
    Tensor* mean = nullptr;
    Tensor* rstd = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, x.shape(),    &y));
    OP_REQUIRES_OK(ctx, ctx->allocate_output(1,    shapeN, &mean));
    OP_REQUIRES_OK(ctx, ctx->allocate_output(2,    shapeN, &rstd));

    float* p1_ptr = nullptr;
    float* p2_ptr = nullptr;
    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));
    if (axis_ == 0)
    {
      p1_ptr = P1->flat<float>().data();
      p2_ptr = P2->flat<float>().data();
    }
             V1*    y_ptr = (V1*)y->flat<T>().data();
          float* mean_ptr = mean->flat<float>().data();
          float* rstd_ptr = rstd->flat<float>().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();

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

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

    for (int r = 0; r < repeat_; r++)
      if (axis_ == last_dim)
      {
        if (S_ > 1 || K_ <= 1024*8)
          LayerNormSegmentedForward_NC<V1,V4>(stream, SMs_, y_ptr, mean_ptr, rstd_ptr, x_ptr, g_ptr, b_ptr, epsilon_, N, S_, K_, rcpK_, relu_);
        else
          LayerNormForward_NC<V1,V4>(stream, SMs_, y_ptr, mean_ptr, rstd_ptr, x_ptr, g_ptr, b_ptr, epsilon_, K_, N, rcpK_, relu_);
      }
      else
        LayerNormForward_CN<V1,V4>(stream, SMs_, y_ptr, mean_ptr, rstd_ptr, p1_ptr, p2_ptr, x_ptr, g_ptr, b_ptr, epsilon_, K_, N, rcpK_, relu_);

    if (bench) delete bench;
  }