```python
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree.

import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline

# Fused CUDA kernel: computes mean(clamp(1 - predictions * targets, min=0))
# in a single pass (multiply + subtract + clamp + reduction all fused).
hinge_loss_cuda_source = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda_runtime.h>
#include <algorithm>

__global__ void hinge_loss_kernel(const float* __restrict__ preds,
                                  const float* __restrict__ targets,
                                  float* __restrict__ out,
                                  long long N,
                                  long long M,
                                  float invN) {
    __shared__ float sdata[256];
    const int tid = threadIdx.x;
    float local = 0.0f;
    const long long stride = (long long)gridDim.x * (long long)blockDim.x;

    // Grid-stride loop: each thread accumulates its clamped hinge values.
    // targets is broadcast along the trailing dimension (idx % M).
    for (long long idx = (long long)blockIdx.x * blockDim.x + tid; idx < N; idx += stride) {
        float p = preds[idx];
        float t = targets[idx % M];
        float v = fmaf(-p, t, 1.0f);   // v = 1 - p * t
        local += v > 0.0f ? v : 0.0f;  // clamp(v, min=0)
    }

    // Block-level reduction in shared memory.
    sdata[tid] = local;
    __syncthreads();
    for (int s = blockDim.x >> 1; s > 0; s >>= 1) {
        if (tid < s) {
            sdata[tid] += sdata[tid + s];
        }
        __syncthreads();
    }

    // Accumulate the mean contribution of this block.
    if (tid == 0) {
        atomicAdd(out, sdata[0] * invN);
    }
}

torch::Tensor hinge_loss_cuda(torch::Tensor predictions, torch::Tensor targets) {
    TORCH_CHECK(predictions.is_cuda() && targets.is_cuda(), "inputs must be CUDA tensors");
    auto preds = predictions.contiguous();
    auto tgts = targets.contiguous();

    const long long N = preds.numel();
    const long long M = tgts.numel();
    TORCH_CHECK(N > 0, "predictions must be non-empty");
    TORCH_CHECK(M >= 1 && (N % M == 0), "unsupported broadcast shape");

    auto out = torch::zeros({}, preds.options());

    const int block = 256;
    const long long blocks_needed = (N + block - 1) / block;
    const int grid = (int)std::min<long long>(blocks_needed, 4096);
    const float invN = 1.0f / (float)N;

    cudaStream_t stream = at::cuda::getCurrentCUDAStream();
    hinge_loss_kernel<<<grid, block, 0, stream>>>(
        preds.data_ptr<float>(),
        tgts.data_ptr<float>(),
        out.data_ptr<float>(),
        N, M, invN);

    return out;
}
"""

hinge_loss_cpp_source = (
    "torch::Tensor hinge_loss_cuda(torch::Tensor predictions, torch::Tensor targets);"
)

# Compile the inline CUDA extension.
hinge_loss_fused = load_inline(
    name="hinge_loss_fused",
    cpp_sources=hinge_loss_cpp_source,
    cuda_sources=hinge_loss_cuda_source,
    functions=["hinge_loss_cuda"],
    verbose=False,
    extra_cflags=["-O3"],
    extra_cuda_cflags=["-O3"],
)


class ModelNew(nn.Module):
    """
    Optimized Hinge Loss using a single fused CUDA kernel that performs
    multiply, subtract, clamp and mean-reduction in one pass.
    """
    def __init__(self):
        super(ModelNew, self).__init__()
        self.hinge_loss = hinge_loss_fused

    def forward(self, predictions, targets):
        if (predictions.is_cuda and targets.is_cuda
                and predictions.dtype == torch.float32
                and targets.dtype == torch.float32
                and predictions.numel() > 0
                and targets.numel() >= 1
                and predictions.numel() % targets.numel() == 0):
            return self.hinge_loss.hinge_loss_cuda(predictions, targets)
        # Fallback to the reference implementation for any other case.
        return torch.mean(torch.clamp(1 - predictions * targets, min=0))
```