diff --git a/src/DotLLM.Cuda/CudaKernels.cs b/src/DotLLM.Cuda/CudaKernels.cs index ec4d059d..b2ffd86d 100644 --- a/src/DotLLM.Cuda/CudaKernels.cs +++ b/src/DotLLM.Cuda/CudaKernels.cs @@ -604,7 +604,7 @@ public void LaunchDequantToF16(nint src, QuantizationType srcDtype, { case QuantizationType.F16: // Already FP16, just copy - CudaDriverApi.cuMemcpyDtoD_v2(dst, src, (nuint)(totalElements * 2)).ThrowOnError(); + CudaDriverApi.cuMemcpyDtoD_v2(dst, src, (nuint)((long)totalElements * 2)).ThrowOnError(); return; case QuantizationType.F32: diff --git a/src/DotLLM.Cuda/CudaTransformerModel.cs b/src/DotLLM.Cuda/CudaTransformerModel.cs index 8591984c..eb80b271 100644 --- a/src/DotLLM.Cuda/CudaTransformerModel.cs +++ b/src/DotLLM.Cuda/CudaTransformerModel.cs @@ -287,7 +287,7 @@ public ITensor Forward(ReadOnlySpan tokenIds, ReadOnlySpan positions, } // 5. Final RmsNorm (last token only) - nint lastHidden = _state.HiddenState + (nint)((seqLen - 1) * hiddenSize * h); + nint lastHidden = _state.HiddenState + (nint)((long)(seqLen - 1) * hiddenSize * h); _kernels.LaunchRmsNorm(lastHidden, _weights.OutputNormWeight, _state.NormOutput, hiddenSize, eps, 1, s); diff --git a/src/DotLLM.Cuda/CudaWeights.cs b/src/DotLLM.Cuda/CudaWeights.cs index 84f9a654..62a0f081 100644 --- a/src/DotLLM.Cuda/CudaWeights.cs +++ b/src/DotLLM.Cuda/CudaWeights.cs @@ -242,7 +242,11 @@ private static nint UploadAndDequant(nint hostPtr, QuantizationType qt, int outputDim, int inputDim, List allocs, CudaKernels kernels, nint stream) { - int totalElements = outputDim * inputDim; + // `checked` rather than widened: every byte size below already casts to long, so this + // element count is the only narrow product — but it is also passed as `int` to + // LaunchConvertF32ToF16 / LaunchDequantToF16, so a long count could not be honoured + // without changing those signatures. Fail loudly instead of wrapping negative (#429). + int totalElements = checked(outputDim * inputDim); if (qt == QuantizationType.F16) {