         rnn_desc,
         xs.size(),
         x_desc,
-        internal::GetRawOffsetData(AsContiguous(x)),
+        internal::GetRawOffsetData(x),
         *hxDesc,
-        internal::GetRawOffsetData(AsContiguous(hx)),
+        internal::GetRawOffsetData(hx),
         *cxDesc,
-        internal::GetRawOffsetData(AsContiguous(cx)),
+        internal::GetRawOffsetData(cx),
         *wDesc,
         internal::GetRawOffsetData(w),
         y_desc,

    );

    Array dw = Empty({(int)weight_size / 4, 1, 1}, hx.dtype(), hx.device());
    CudnnFilterDescriptor dwDesc{AsContiguous(dw)};
    
    handle.Call(
        cudnnRNNBackwardWeights,
        rnn_desc,
        xs.size(),
        xs_desc,
        internal::GetRawOffsetData(AsContiguous(x)),
        *hx_desc,
        internal::GetRawOffsetData(AsContiguous(hx)),
        ys_desc,
        internal::GetRawOffsetData(AsContiguous(y)),
        workspace,
        workSize,
        *dwDesc,

    handle.Call(cudnnGetRNNWorkspaceSize, rnn_desc, xs.size(), xs_desc, &workSize);
    cudaMalloc((void**)&workspace, workSize);

    hx = AsContiguous(hx.AsType(Dtype::kFloat32));
    cx = AsContiguous(cx.AsType(Dtype::kFloat32));
    dhy = AsContiguous(dhy.AsType(Dtype::kFloat32));
    dcy = AsContiguous(dcy.AsType(Dtype::kFloat32));

    CudnnTensorDescriptor hx_desc{hx};
    CudnnTensorDescriptor cx_desc{cx};
    CudnnTensorDescriptor dhy_desc{dhy};
    CudnnTensorDescriptor dcy_desc{dcy};

    Array dhx = Empty(hx.shape(), hx.dtype(), hx.device());
    CudnnTensorDescriptor dhx_desc{dhx};
