class_docstr: Implement CrossentropySoftmax1HotWithBiasDx on the gpu.
  
  Gradient wrt x of the CrossentropySoftmax1Hot Op.
code: def c_code(self, node, nodename, inp, out, sub):
      typecode_dx = pygpu.gpuarray.dtype_to_typecode(
          node.outputs[0].dtype
      )
      itemsize_dnll = np.dtype(node.inputs[0].dtype).itemsize
      itemsize_sm = np.dtype(node.inputs[1].dtype).itemsize
      itemsize_y_idx = np.dtype(node.inputs[2].dtype).itemsize
      itemsize_dx = np.dtype(node.outputs[0].dtype).itemsize
      dtype_dnll = node.inputs[0].dtype
      dtype_sm = node.inputs[1].dtype
      dtype_y_idx = node.inputs[2].dtype
      dtype_dx = node.outputs[0].dtype
      type_intp = gpuarray.dtype_to_ctype(np.intp)
      dnll, sm, y_idx = inp
      (dx,) = out
      fail = sub["fail"]
      ctx = sub["params"]
      k_var = "kCrossEntropySoftmax1HotWithBiasDx_" + nodename
      err_check = (
          """
              if (err != GA_NO_ERROR) {
                  PyErr_Format(PyExc_RuntimeError,
                               "gpuarray error: %(k_var)s: %%s.",
                               GpuKernel_error(&%(k_var)s, err));
                  %(fail)s;
              }
          """
          % locals()
      )
      return (
          """
          // Get `dnll.shape[0]` or set it to zero if `dnll` is a scalar.
          const ssize_t %(dnll)s_dims0 = (PyGpuArray_NDIM(%(dnll)s) > 0 ?
                                          PyGpuArray_DIMS(%(dnll)s)[0] :
                                          (ssize_t) 0);
          // Get `dnll.strides[0]` and set it to zero if `dnll` is a scalar
          // or a vector with just one element.
          const ssize_t %(dnll)s_strides0 = (%(dnll)s_dims0 > 1 ?
                                             PyGpuArray_STRIDES(%(dnll)s)[0] :
                                             (ssize_t) 0);
          if ((PyGpuArray_NDIM(%(dnll)s) > 1)
              || (PyGpuArray_NDIM(%(sm)s) != 2)
              || (PyGpuArray_NDIM(%(y_idx)s) != 1))
          {
              PyErr_SetString(PyExc_ValueError, "rank error");
              %(fail)s;
          }
          if (%(dnll)s_dims0 !=
              PyGpuArray_DIMS(%(sm)s)[0] && %(dnll)s_dims0 > 1)
          {
              PyErr_Format(PyExc_ValueError,
                           "dnll.shape[0] == %%i, but sm.shape[0] == %%i",
                           %(dnll)s_dims0,
                           PyGpuArray_DIMS(%(sm)s)[0]);
              %(fail)s;
          }
          if (%(dnll)s_dims0 !=
              PyGpuArray_DIMS(%(y_idx)s)[0] && %(dnll)s_dims0 > 1)
          {
              PyErr_SetString(PyExc_ValueError,
                              "dnll.shape[0] != y_idx.shape[0]");
              %(fail)s;
          }
          if (PyGpuArray_DIMS(%(sm)s)[0] !=
              PyGpuArray_DIMS(%(y_idx)s)[0])
          {
              PyErr_SetString(PyExc_ValueError,
                              "sm.shape[0] != y_idx.shape[0]");
              %(fail)s;
          }
          if ((NULL == %(dx)s)
              || (PyGpuArray_DIMS(%(dx)s)[0] !=
                  PyGpuArray_DIMS(%(sm)s)[0])
              || (PyGpuArray_DIMS(%(dx)s)[1] !=
                  PyGpuArray_DIMS(%(sm)s)[1]))
          {
              Py_XDECREF(%(dx)s);
              %(dx)s = pygpu_empty(2, PyGpuArray_DIMS(%(sm)s),
                                   %(typecode_dx)s, GA_C_ORDER,
                                   %(ctx)s, Py_None);
              if (!%(dx)s) {
                  %(fail)s
              }
          }
          {
              size_t n_blocks[3] = {std::min(PyGpuArray_DIMS(%(dx)s)[0], (size_t)256), 1, 1};
              size_t threads_per_block[3] = {std::min(PyGpuArray_DIMS(%(dx)s)[1], (size_t)256), 1, 1};
              ssize_t stride_DNLL0 = %(dnll)s_strides0 / %(itemsize_dnll)s;
              ssize_t stride_SM0 = PyGpuArray_STRIDES(%(sm)s)[0] / %(itemsize_sm)s;
              ssize_t stride_SM1 = PyGpuArray_STRIDES(%(sm)s)[1] / %(itemsize_sm)s;
              ssize_t stride_YIDX0 = PyGpuArray_STRIDES(%(y_idx)s)[0] / %(itemsize_y_idx)s;
              ssize_t stride_DX0 = PyGpuArray_STRIDES(%(dx)s)[0] / %(itemsize_dx)s;
              ssize_t stride_DX1 = PyGpuArray_STRIDES(%(dx)s)[1] / %(itemsize_dx)s;
              void *kernel_params[] = {
                  (void *)&PyGpuArray_DIMS(%(dx)s)[0],
                  (void *)&PyGpuArray_DIMS(%(dx)s)[1],
                  (void *)%(dnll)s->ga.data, (void *)&%(dnll)s->ga.offset,
                  (void *)&stride_DNLL0,
                  (void *)%(sm)s->ga.data, (void *)&%(sm)s->ga.offset,
                  (void *)&stride_SM0, (void *)&stride_SM1,
                  (void *)%(y_idx)s->ga.data, (void *)&%(y_idx)s->ga.offset,
                  (void *)&stride_YIDX0,
                  (void *)%(dx)s->ga.data, (void *)&%(dx)s->ga.offset,
                  (void *)&stride_DX0, (void *)&stride_DX1};
              int err = GpuKernel_call(&%(k_var)s, 3, n_blocks, threads_per_block, 0, kernel_params);
              %(err_check)s
          }
          assert(%(dx)s);
          """
          % locals()
      )
  
imports: from __future__ import absolute_import, print_function, division
  import numpy
  from theano import Op, Apply
  from six import StringIO
  from .basic_ops import as_gpuarray_variable, GpuKernelBase, Kernel, gpuarray_helper_inc_dir, infer_context_name
  from .type import GpuArrayType
  from .fp16_help import work_dtype, load_w, write_w
label_desc: Use image node_id 4 for calling the GpuCrossentropySoftmax1HotWithBiasDx obj's underlying member method code with example usage: obj.c_code(node, nodename, inp, out, sub) and returns: unknown