Write a custom CUDA kernel to optimize `torch.nn.MultiMarginLoss`.

The original operation is defined by the formula:
`loss(x, y) = sum(max(0, margin - x[y] + x[i]))^p / C` for `i != y`.
This is computed for each sample in the batch, and then a reduction is applied.

**Problem Analysis:**
The standard PyTorch implementation of this loss is memory-bound and inefficient due to its operational complexity. It requires a sequence of advanced indexing (`gather`), broadcasting, masking (for `i != y`), element-wise operations (`max`, `pow`), and two levels of reduction (first over classes, then over the batch). Each step materializes large intermediate tensors of size (N, C), leading to high memory bandwidth consumption and kernel launch overhead.

**Optimization Strategy: Fused Block-Level Parallelism**

The optimization strategy fuses the entire per-sample computation into a single CUDA kernel, using a block-per-sample parallelization model.

1.  **Parallelization Model**: The kernel is launched with a grid of `N` blocks, where `N` is the batch size. Each thread block is exclusively responsible for calculating the total loss for a single sample.

2.  **Shared Memory for Broadcasting**: For each sample (i.e., each block), the target class index `y` and its corresponding score `x[y]` are loaded once into **shared memory**. A `__syncthreads()` call makes this data available to all threads in the block, serving as an extremely fast, localized broadcast mechanism.

3.  **Fused Intra-Block Computation**: The threads within a block collaboratively iterate over the `C` classes. Each thread computes the hinge loss `max(0, ...)` for a subset of the classes, accumulating a partial sum in its local registers. This fuses indexing, subtraction, clamping (`max`), and power (`p`) operations.

4.  **Efficient Intra-Block Reduction**: After processing all classes, a highly-optimized parallel reduction is performed using shared memory. The threads sum their partial sums together in a tree-like fashion, yielding the total loss for the sample in a few clock cycles.

5.  **Finalization and Output**: The first thread of each block performs the final division by `C` and applies the class `weight` (if provided), then writes the final scalar loss for its assigned sample to the output tensor.

This kernel directly produces the result for `reduction='none'`. For `'mean'` and `'sum'`, a simple, fast reduction is applied to the kernel's small 1D output tensor. This approach transforms a complex, multi-stage, memory-intensive workflow into a single, efficient, compute-bound kernel pass.
  
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 = 512
NUM_CLASSES = 4096 
REDUCTION = 'mean'
P = 1 # 1 for L1 hinge, 2 for L2
MARGIN = 1.0

class Model(nn.Module):
    """
    使用 PyTorch 内置的 torch.nn.MultiMarginLoss 作为基准模型。
    """
    def __init__(self, p=1, margin=1.0, reduction='mean'):
        super(Model, self).__init__()
        # weight is not benchmarked for simplicity, but the CUDA kernel supports it.
        self.loss_fn = nn.MultiMarginLoss(p=p, margin=margin, reduction=reduction)
    
    def forward(self, input_tensor: torch.Tensor, target_tensor: torch.Tensor) -> torch.Tensor:
        return self.loss_fn(input_tensor, target_tensor)

def get_inputs():
    input_tensor = torch.randn(BATCH_SIZE, NUM_CLASSES, dtype=torch.float32)
    
    target_tensor = torch.randint(0, NUM_CLASSES, (BATCH_SIZE,), dtype=torch.long)
    
    return [input_tensor.contiguous(), target_tensor.contiguous()]

def get_init_inputs():
    return [P, MARGIN, REDUCTION]