You write custom CUDA kernels to replace the pytorch operators in the given architecture to get speedups. 

    You have complete freedom to choose the set of operators you want to replace. You may make the decision to replace some operators with custom CUDA kernels and leave others unchanged. You may replace multiple operators with custom implementations, consider operator fusion opportunities (combining multiple operators into a single kernel, for example, combining matmul+relu), or algorithmic changes (such as online softmax). You are only limited by your imagination.


        Here's an example to show you the syntax of inline embedding custom CUDA operators in torch: The example given architecture is: 

        ``` 

        # 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
import torch.nn.functional as F


class Model(nn.Module):
    def __init__(self) -> None:
        super().__init__()

    def forward(self, a, b):
        return a + b


def get_inputs():
    # randomly generate input tensors based on the model architecture
    a = torch.randn(1, 128).cuda()
    b = torch.randn(1, 128).cuda()
    return [a, b]


def get_init_inputs():
    # randomly generate tensors required for initialization based on the model architecture
    return []

        ``` 

        The example new arch with custom CUDA kernels looks like this:
        ```
        # 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
import torch.nn.functional as F
from torch.utils.cpp_extension import load_inline

# Define the custom CUDA kernel for element-wise addition
elementwise_add_source = """
#include <torch/extension.h>
#include <cuda_runtime.h>

__global__ void elementwise_add_kernel(const float* a, const float* b, float* out, int size) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (idx < size) {
        out[idx] = a[idx] + b[idx];
    }
}

torch::Tensor elementwise_add_cuda(torch::Tensor a, torch::Tensor b) {
    auto size = a.numel();
    auto out = torch::zeros_like(a);

    const int block_size = 256;
    const int num_blocks = (size + block_size - 1) / block_size;

    elementwise_add_kernel<<<num_blocks, block_size>>>(a.data_ptr<float>(), b.data_ptr<float>(), out.data_ptr<float>(), size);

    return out;
}
"""

elementwise_add_cpp_source = (
    "torch::Tensor elementwise_add_cuda(torch::Tensor a, torch::Tensor b);"
)

# Compile the inline CUDA code for element-wise addition
elementwise_add = load_inline(
    name="elementwise_add",
    cpp_sources=elementwise_add_cpp_source,
    cuda_sources=elementwise_add_source,
    functions=["elementwise_add_cuda"],
    verbose=True,
    extra_cflags=[""],
    extra_ldflags=[""],
)


class ModelNew(nn.Module):
    def __init__(self) -> None:
        super().__init__()
        self.elementwise_add = elementwise_add

    def forward(self, a, b):
        return self.elementwise_add.elementwise_add_cuda(a, b)

        ``` 

        
    You are given the following architecture: 

    ```
    # 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

class Model(nn.Module):
    """
    Simple model that performs a single matrix multiplication (C = A * B)
    """
    def __init__(self):
        super(Model, self).__init__()
    
    def forward(self, A: torch.Tensor, B: torch.Tensor) -> torch.Tensor:
        """
        Performs matrix multiplication.

        Args:
            A: Input tensor of shape (M, K).
            B: Input tensor of shape (K, N).

        Returns:
            Output tensor of shape (M, N).
        """
        return torch.matmul(A, B)

M = 1024 * 2
K = 4096 * 2
N = 2048 * 2

def get_inputs():
    A = torch.rand(M, K)
    B = torch.rand(K, N)
    return [A, B]

def get_init_inputs():
    return []  # No special initialization inputs needed
    ```
    
Optimize the architecture named Model with custom CUDA operators! Name your optimized output architecture ModelNew. Output the new code in codeblocks. Please generate real code, NOT pseudocode, make sure the code compiles and is fully functional. Just output the new model code, no other text, and NO testing code! 



This is turn 5 of 6 for this task. Your previous solution (turn 4) was:
```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 os
import glob

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


def _cublas_ldflags():
    """Locate libcublas shipped with the pip CUDA toolkit (or a system CUDA)."""
    sp = os.path.dirname(os.path.dirname(os.path.abspath(torch.__file__)))
    patterns = [
        os.path.join(sp, "nvidia", "*", "lib", "libcublas.so*"),
        os.path.join(sp, "nvidia", "*", "lib64", "libcublas.so*"),
        "/usr/local/cuda/lib64/libcublas.so*",
        "/usr/local/cuda/lib/libcublas.so*",
        "/usr/lib/x86_64-linux-gnu/libcublas.so*",
        "/usr/lib64/libcublas.so*",
    ]
    found = []
    for pat in patterns:
        found.extend(sorted(glob.glob(pat)))
    found = [f for f in found if "stubs" not in f]
    if not found:
        return ["-lcublas"]
    unversioned = [f for f in found if f.endswith(".so")]
    lib = unversioned[0] if unversioned else found[0]
    libdir = os.path.dirname(lib)
    return ["-L" + libdir, "-Wl,-rpath," + libdir, lib]


# Optimized GEMM:
#  * FP32 inputs are converted to FP16 with fast, vectorized custom kernels
#    (one launch per K-chunk of A and B) and multiplied with cuBLAS tensor-core
#    GemmEx (FP32 accumulate / FP32 output).
#  * The K dimension is split into chunks. Chunk conversions run on a side
#    (bandwidth-bound) stream while previously converted chunks are already
#    being multiplied on the main stream (compute-bound), so most of the
#    conversion time is hidden behind the tensor-core GEMMs.
#  * The cuBLAS algorithm for the chunk shape is autotuned once and cached.
_cpp_source = "torch::Tensor matmul_cuda(torch::Tensor A, torch::Tensor B);"

_cuda_source = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <c10/cuda/CUDAGuard.h>
#include <cublas_v2.h>
#include <cuda_runtime.h>
#include <cuda_fp16.h>
#include <map>
#include <mutex>
#include <tuple>

namespace {

constexpr int kMaxDevices = 64;
constexpr int kMaxChunks = 8;
constexpr size_t kWorkspaceBytes = (size_t)128 * 1024 * 1024;

struct DevState {
    cublasHandle_t handle = nullptr;
    void* workspace = nullptr;
    cudaStream_t conv_stream = nullptr;
    cudaEvent_t start_event = nullptr;
    cudaEvent_t conv_events[kMaxChunks] = {nullptr};
    bool init_attempted = false;
    bool ok = false;
};

DevState g_dev[kMaxDevices];
std::mutex g_dev_mu;
std::mutex g_cache_mu;
std::map<std::tuple<int, int64_t, int64_t, int64_t>, int> g_algo_cache;

DevState& get_state(int device) {
    DevState& st = g_dev[device];
    if (!st.init_attempted) {
        std::lock_guard<std::mutex> lock(g_dev_mu);
        if (!st.init_attempted) {
            st.init_attempted = true;
            const c10::cuda::CUDAGuard guard(device);
            do {
                if (cublasCreate(&st.handle) != CUBLAS_STATUS_SUCCESS) break;
                if (cudaMalloc(&st.workspace, kWorkspaceBytes) != cudaSuccess) break;
                if (cublasSetWorkspace(st.handle, st.workspace, kWorkspaceBytes)
                        != CUBLAS_STATUS_SUCCESS) break;
                if (cudaStreamCreateWithFlags(&st.conv_stream, cudaStreamNonBlocking)
                        != cudaSuccess) break;
                if (cudaEventCreateWithFlags(&st.start_event, cudaEventDisableTiming)
                        != cudaSuccess) break;
                bool ev_ok = true;
                for (int i = 0; i < kMaxChunks; ++i) {
                    if (cudaEventCreateWithFlags(&st.conv_events[i],
                                                 cudaEventDisableTiming)
                            != cudaSuccess) {
                        ev_ok = false;
                        break;
                    }
                }
                if (!ev_ok) break;
                st.ok = true;
            } while (0);
        }
    }
    return st;
}

// Converts a [rows x width8*8] FP32 tile (row stride ld_src) to FP16
// (row stride ld_dst). 8 elements per thread, 32B loads / 16B stores.
__global__ void convert_tile_kernel(const float* __restrict__ src,
                                    __half* __restrict__ dst,
                                    int width8, long ld_src, long ld_dst) {
    const int m = blockIdx.y;
    const int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i >= width8) return;
    const float4* s = reinterpret_cast<const float4*>(src + (long)m * ld_src);
    const float4 x = __ldcs(s + 2 * i);
    const float4 y = __ldcs(s + 2 * i + 1);
    __half2 h0 = __floats2half2_rn(x.x, x.y);
    __half2 h1 = __floats2half2_rn(x.z, x.w);
    __half2 h2 = __floats2half2_rn(y.x, y.y);
    __half2 h3 = __floats2half2_rn(y.z, y.w);
    uint4 packed;
    packed.x = *reinterpret_cast<unsigned*>(&h0);
    packed.y = *reinterpret_cast<unsigned*>(&h1);
    packed.z = *reinterpret_cast<unsigned*>(&h2);
    packed.w = *reinterpret_cast<unsigned*>(&h3);
    reinterpret_cast<uint4*>(dst + (long)m * ld_dst)[i] = packed;
}

inline cublasStatus_t run_gemm(cublasHandle_t handle, int64_t M, int64_t N,
                               int64_t k, const void* Bh, int64_t ldb,
                               const void* Ah, int64_t lda, void* C,
                               int64_t ldc, float beta, int algo) {
    const float alpha = 1.0f;
    // Row-major C(MxN) = A(Mxk) * B(kxN) as column-major C^T = B^T * A^T.
    return cublasGemmEx(handle, CUBLAS_OP_N, CUBLAS_OP_N,
                        (int)N, (int)M, (int)k, &alpha,
                        Bh, CUDA_R_16F, (int)ldb,
                        Ah, CUDA_R_16F, (int)lda,
                        &beta, C, CUDA_R_32F, (int)ldc,
                        CUBLAS_COMPUTE_32F, (cublasGemmAlgo_t)algo);
}

int autotune_algo(cublasHandle_t handle, int64_t M, int64_t N, int64_t W,
                  const void* Bh, int64_t ldb, const void* Ah, int64_t lda,
                  void* C, int64_t ldc, cudaStream_t stream) {
    static const int cands[] = {-1, 99,
                                100, 101, 102, 103, 104, 105, 106, 107,
                                108, 109, 110, 111, 112, 113, 114, 115};
    cudaEvent_t t0, t1;
    if (cudaEventCreate(&t0) != cudaSuccess) return -1;
    if (cudaEventCreate(&t1) != cudaSuccess) { cudaEventDestroy(t0); return -1; }
    float best_ms = 1e30f;
    int best_algo = -1;
    for (size_t ci = 0; ci < sizeof(cands) / sizeof(cands[0]); ++ci) {
        const int algo = cands[ci];
        if (run_gemm(handle, M, N, W, Bh, ldb, Ah, lda, C, ldc, 0.0f, algo)
                != CUBLAS_STATUS_SUCCESS) {
            continue;
        }
        cudaEventRecord(t0, stream);
        for (int r = 0; r < 3; ++r) {
            run_gemm(handle, M, N, W, Bh, ldb, Ah, lda, C, ldc, 0.0f, algo);
        }
        cudaEventRecord(t1, stream);
        cudaStreamSynchronize(stream);
        float ms = 0.0f;
        cudaEventElapsedTime(&ms, t0, t1);
        if (ms < best_ms) {
            best_ms = ms;
            best_algo = algo;
        }
    }
    cudaEventDestroy(t0);
    cudaEventDestroy(t1);
    return best_algo;
}

}  // namespace

torch::Tensor matmul_cuda(torch::Tensor A, torch::Tensor B) {
    TORCH_CHECK(A.is_cuda() && B.is_cuda(), "A and B must be CUDA tensors");
    TORCH_CHECK(A.dim() == 2 && B.dim() == 2, "A and B must be 2-D");
    TORCH_CHECK(A.scalar_type() == at::kFloat && B.scalar_type() == at::kFloat,
                "A and B must be float32");

    const c10::cuda::OptionalCUDAGuard device_guard(A.device());

    auto Ac = A.contiguous();
    auto Bc = B.contiguous();
    const int64_t M = Ac.size(0);
    const int64_t K = Ac.size(1);
    const int64_t N = Bc.size(1);
    TORCH_CHECK(Bc.size(0) == K, "inner dimension mismatch");

    auto C = at::empty({M, N}, Ac.options());
    if (M == 0 || N == 0) return C;
    if (K == 0) { C.zero_(); return C; }

    const int device = (int)Ac.get_device();
    cudaStream_t stream = at::cuda::getCurrentCUDAStream().stream();

    bool fast = (((M | N | K) & 7) == 0) && (device == Bc.get_device()) &&
                (device >= 0 && device < kMaxDevices) && (M <= 65535) &&
                (K <= 65535L * 8 * 256);
    DevState* stp = nullptr;
    if (fast) {
        stp = &get_state(device);
        if (!stp->ok) fast = false;
    }
    if (!fast) {
        C.copy_(at::matmul(Ac, Bc));
        return C;
    }
    DevState& st = *stp;
    cublasSetStream(st.handle, stream);

    // Decide the number of K chunks (conversion/compute pipelining).
    int nchunks = 1;
    if (K >= 4096 && (K % 4) == 0 && ((K / 4) % 8) == 0 && (K / 4) >= 1024) {
        nchunks = 4;
    } else if (K >= 2048 && (K % 2) == 0 && ((K / 2) % 8) == 0 &&
               (K / 2) >= 1024) {
        nchunks = 2;
    }
    if (nchunks > kMaxChunks) nchunks = kMaxChunks;
    const int64_t W = K / nchunks;

    auto half_opts = Ac.options().dtype(at::kHalf);
    auto Ah = at::empty({M, K}, half_opts);
    auto Bh = at::empty({K, N}, half_opts);

    const float* Aptr = Ac.data_ptr<float>();
    const float* Bptr = Bc.data_ptr<float>();
    __half* Ahptr = reinterpret_cast<__half*>(Ah.data_ptr());
    __half* Bhptr = reinterpret_cast<__half*>(Bh.data_ptr());
    float* Cptr = C.data_ptr<float>();

    // Cache key for the autotuned chunk-GEMM algorithm.
    const auto key = std::make_tuple(device, M, N, W);
    int algo = -1;  // CUBLAS_GEMM_DEFAULT
    bool have_cached = false;
    {
        std::lock_guard<std::mutex> lock(g_cache_mu);
        auto it = g_algo_cache.find(key);
        if (it != g_algo_cache.end()) {
            algo = it->second;
            have_cached = true;
        }
    }

    // ---- Pipeline: conversions on side stream, GEMMs on main stream ----
    cudaEventRecord(st.start_event, stream);
    cudaStreamWaitEvent(st.conv_stream, st.start_event, 0);

    const int tpb = 256;
    const int a_w8 = (int)(W / 8);
    const dim3 gridA((a_w8 + tpb - 1) / tpb, (unsigned)M);
    const int b_w8 = (int)(N / 8);
    const dim3 gridB((b_w8 + tpb - 1) / tpb, (unsigned)W);

    for (int i = 0; i < nchunks; ++i) {
        const int64_t k0 = (int64_t)i * W;
        convert_tile_kernel<<<gridA, tpb, 0, st.conv_stream>>>(
            Aptr + k0, Ahptr + k0, a_w8, (long)K, (long)K);
        convert_tile_kernel<<<gridB, tpb, 0, st.conv_stream>>>(
            Bptr + k0 * N, Bhptr + k0 * N, b_w8, (long)N, (long)N);
        cudaEventRecord(st.conv_events[i], st.conv_stream);
    }

    for (int i = 0; i < nchunks; ++i) {
        const int64_t k0 = (int64_t)i * W;
        cudaStreamWaitEvent(stream, st.conv_events[i], 0);
        const float beta = (i == 0) ? 0.0f : 1.0f;
        const cublasStatus_t status =
            run_gemm(st.handle, M, N, W, Bhptr + k0 * N, N, Ahptr + k0, K,
                     Cptr, N, beta, algo);
        if (status != CUBLAS_STATUS_SUCCESS) {
            C.copy_(at::matmul(Ac, Bc));
            return C;
        }
    }

    // ---- One-time autotune of the cuBLAS algorithm for this chunk shape ----
    if (!have_cached) {
        auto scratch = at::empty({M, N}, Ac.options());
        const int best = autotune_algo(st.handle, M, N, W, Bhptr, N, Ahptr, K,
                                       scratch.data_ptr<float>(), N, stream);
        std::lock_guard<std::mutex> lock(g_cache_mu);
        g_algo_cache[key] = best;
    }

    return C;
}
"""

_matmul_ext = load_inline(
    name="matmul_pipelined_fp16tc_v4",
    cpp_sources=_cpp_source,
    cuda_sources=_cuda_source,
    functions=["matmul_cuda"],
    verbose=False,
    extra_cflags=["-O3"],
    extra_cuda_cflags=["-O3"],
    extra_ldflags=_cublas_ldflags(),
)


class ModelNew(nn.Module):
    """
    Optimized model that performs a single matrix multiplication (C = A * B)
    using FP16 tensor cores via cuBLAS GemmEx (FP32 accumulation/output) with
    K-chunk pipelining: FP32->FP16 conversions on a side stream are overlapped
    with tensor-core GEMMs on the main stream.
    """

    def __init__(self):
        super(ModelNew, self).__init__()
        self._matmul = _matmul_ext

    def forward(self, A: torch.Tensor, B: torch.Tensor) -> torch.Tensor:
        if (A.is_cuda and B.is_cuda and A.dtype == torch.float32
                and B.dtype == torch.float32 and A.dim() == 2 and B.dim() == 2):
            return self._matmul.matmul_cuda(A, B)
        return torch.matmul(A, B)
```
Result of evaluating it:
The solution is correct on the test inputs. Mean runtime 0.804 ms; the PyTorch reference (with TF32 enabled) takes 1.15 ms; speedup 1.430x.
Profiler, top device kernels of one forward pass of your solution:
| device kernel | total device time (us) | calls |
|---|---|---|
| void cutlass::Kernel2<cutlass_80_tensorop_s16816gemm_f16_128x128_32x4_nn_align8>(cutlass_8 | 679.0 | 4 |
| (anonymous namespace)::convert_tile_kernel(float const*, __half*, int, long, long) | 265.8 | 8 |

The fastest correct solution so far (1.539x speedup) is:
```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 os
import glob

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


def _cublas_ldflags():
    """Locate libcublas shipped with the pip CUDA toolkit (or a system CUDA)."""
    sp = os.path.dirname(os.path.dirname(os.path.abspath(torch.__file__)))
    patterns = [
        os.path.join(sp, "nvidia", "*", "lib", "libcublas.so*"),
        os.path.join(sp, "nvidia", "*", "lib64", "libcublas.so*"),
        "/usr/local/cuda/lib64/libcublas.so*",
        "/usr/local/cuda/lib/libcublas.so*",
        "/usr/lib/x86_64-linux-gnu/libcublas.so*",
        "/usr/lib64/libcublas.so*",
    ]
    found = []
    for pat in patterns:
        found.extend(sorted(glob.glob(pat)))
    found = [f for f in found if "stubs" not in f]
    if not found:
        return ["-lcublas"]
    unversioned = [f for f in found if f.endswith(".so")]
    lib = unversioned[0] if unversioned else found[0]
    libdir = os.path.dirname(lib)
    return ["-L" + libdir, "-Wl,-rpath," + libdir, lib]


# Optimized GEMM: cast FP32 inputs to FP16 and run a cuBLAS tensor-core GEMM
# (cublasGemmEx) with FP32 accumulation and FP32 output. FP16 has the same
# 10-bit mantissa as TF32, so precision is TF32-comparable while tensor-core
# throughput is roughly doubled. A private cached cuBLAS handle (with a large
# workspace) is used so no internal ATen cuBLAS headers are required.
_cpp_source = "torch::Tensor matmul_cuda(torch::Tensor A, torch::Tensor B);"

_cuda_source = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <c10/cuda/CUDAGuard.h>
#include <cublas_v2.h>
#include <cuda_runtime.h>
#include <mutex>

namespace {

cublasHandle_t get_blas_handle(int device, cudaStream_t stream) {
    static cublasHandle_t handles[64] = {nullptr};
    static void* workspaces[64] = {nullptr};
    static std::mutex mu;
    if (device < 0 || device >= 64) return nullptr;
    if (handles[device] == nullptr) {
        std::lock_guard<std::mutex> lock(mu);
        if (handles[device] == nullptr) {
            const c10::cuda::CUDAGuard guard(device);
            cublasHandle_t h = nullptr;
            if (cublasCreate(&h) != CUBLAS_STATUS_SUCCESS) return nullptr;
            const size_t ws_bytes = (size_t)32 * 1024 * 1024;
            if (cudaMalloc(&workspaces[device], ws_bytes) == cudaSuccess) {
                cublasSetWorkspace(h, workspaces[device], ws_bytes);
            }
            handles[device] = h;
        }
    }
    cublasSetStream(handles[device], stream);
    return handles[device];
}

}  // namespace

torch::Tensor matmul_cuda(torch::Tensor A, torch::Tensor B) {
    TORCH_CHECK(A.is_cuda() && B.is_cuda(), "A and B must be CUDA tensors");
    TORCH_CHECK(A.dim() == 2 && B.dim() == 2, "A and B must be 2-D");
    TORCH_CHECK(A.scalar_type() == at::kFloat && B.scalar_type() == at::kFloat,
                "A and B must be float32");

    const c10::cuda::OptionalCUDAGuard device_guard(A.device());

    auto Ac = A.contiguous();
    auto Bc = B.contiguous();
    const int64_t M = Ac.size(0);
    const int64_t K = Ac.size(1);
    const int64_t N = Bc.size(1);
    TORCH_CHECK(Bc.size(0) == K, "inner dimension mismatch");

    auto C = at::empty({M, N}, Ac.options());
    if (M == 0 || N == 0) return C;
    if (K == 0) { C.zero_(); return C; }

    // The fast tensor-core path wants 8-element divisibility and one device.
    const bool fast = (((M | N | K) & 7) == 0) &&
                      (Ac.get_device() == Bc.get_device());
    if (fast) {
        auto Ah = Ac.to(at::kHalf);
        auto Bh = Bc.to(at::kHalf);
        cublasHandle_t handle = get_blas_handle(
            (int)Ac.get_device(), at::cuda::getCurrentCUDAStream().stream());
        if (handle != nullptr) {
            const float alpha = 1.0f;
            const float beta = 0.0f;
            // Row-major C(MxN) = A(MxK) * B(KxN) is computed as the
            // column-major gemm C^T = B^T * A^T with m=N, n=M, k=K.
            cublasStatus_t status = cublasGemmEx(
                handle, CUBLAS_OP_N, CUBLAS_OP_N,
                (int)N, (int)M, (int)K,
                &alpha,
                Bh.data_ptr(), CUDA_R_16F, (int)N,
                Ah.data_ptr(), CUDA_R_16F, (int)K,
                &beta,
                C.data_ptr(), CUDA_R_32F, (int)N,
                CUBLAS_COMPUTE_32F, CUBLAS_GEMM_DEFAULT);
            if (status == CUBLAS_STATUS_SUCCESS) {
                return C;
            }
        }
        // Fallback: fp16 matmul (fp32 accumulate) then upcast to fp32.
        C.copy_(at::matmul(Ah, Bh));
        return C;
    }

    C.copy_(at::matmul(Ac, Bc));
    return C;
}
"""

_matmul_ext = load_inline(
    name="matmul_gemmex_fp16tc_v3",
    cpp_sources=_cpp_source,
    cuda_sources=_cuda_source,
    functions=["matmul_cuda"],
    verbose=False,
    extra_cflags=["-O3"],
    extra_cuda_cflags=["-O3"],
    extra_ldflags=_cublas_ldflags(),
)


class ModelNew(nn.Module):
    """
    Optimized model that performs a single matrix multiplication (C = A * B)
    using FP16 tensor cores via cuBLAS GemmEx with FP32 accumulation/output.
    """

    def __init__(self):
        super(ModelNew, self).__init__()
        self._matmul = _matmul_ext

    def forward(self, A: torch.Tensor, B: torch.Tensor) -> torch.Tensor:
        if (A.is_cuda and B.is_cuda and A.dtype == torch.float32
                and B.dtype == torch.float32 and A.dim() == 2 and B.dim() == 2):
            return self._matmul.matmul_cuda(A, B)
        return torch.matmul(A, B)
```

Write an improved complete ModelNew: fix any error, and if the solution is already correct, make it faster. Output the new code in one ```python codeblock. Just the model code, no other text, and NO testing code.
