Write a custom CUDA kernel to optimize `torch.cumsum`.

The operation computes the cumulative sum of elements along a given dimension. Mathematically, `y_i = sum(x_0 ... x_i)`.

**Problem Analysis:**
1.  **Algorithmic Challenge**: `cumsum` is inherently sequential. Parallelizing it requires a Scan algorithm (Prefix Sum). While Blelloch scan is work-efficient ($O(N)$), it computes an exclusive scan and requires a final addition step, which can introduce numerical variance compared to PyTorch's sequential accumulation.
2.  **Precision Sensitivity**: With sequence lengths like 2048, standard `float64` accumulation order differences lead to rounding errors that exceed strict validation thresholds (`1e-5`).
3.  **Memory Bandwidth**: The operation is memory-bound. Efficient use of Shared Memory is critical to avoid repeated Global Memory access.

**Optimization Strategy: Double-Buffered Hillis-Steele Scan in Double Precision**

To achieve both robustness (passing precision checks on random inputs) and high performance, the following strategy is used:

1.  **Hillis-Steele Algorithm (Inclusive Scan)**: Unlike Blelloch, Hillis-Steele directly computes the inclusive scan. Although its work complexity is $O(N \log N)$, it maps perfectly to the GPU warp structure and avoids the numerical jitter of the exclusive-to-inclusive conversion step.

2.  **High Precision Accumulation**: The kernel performs all internal accumulation using **`double` (FP64)**. Data is loaded from global memory, promoted to double, processed, and cast back to float only at the final write. This effectively masks intermediate rounding errors.

3.  **Double Buffering (Ping-Pong)**: To handle read-after-write dependencies between scan steps without race conditions, we use two Shared Memory buffers. In each iteration, threads read from one buffer and write to the other, swapping pointers after synchronization.

4.  **Block-per-Row Parallelism**: Each CUDA block processes one entire row (sequence). With 1024 threads processing 2 elements each, we handle sequence lengths up to 2048 entirely in on-chip memory.
  
Here's an example to show you the syntax of inline embedding custom CUDA operators in torch: The example given architecture is:   
  
```python
import torch
import torch.nn as nn

BATCH_SIZE = 2048
SEQ_LEN = 2048  
SHAPE = (BATCH_SIZE, SEQ_LEN)
DIM = 1

class Model(nn.Module):
    """
    使用 PyTorch 内置的 torch.cumsum 作为基准模型。
    """
    def __init__(self, dim):
        super(Model, self).__init__()
        self.dim = dim
    
    def forward(self, input_tensor: torch.Tensor) -> torch.Tensor:
        return torch.cumsum(input_tensor, dim=self.dim)

def get_inputs():
    input_tensor = torch.randn(SHAPE, dtype=torch.float64)
    return [input_tensor.contiguous()]

def get_init_inputs():
    return [DIM]