You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Buffer.BlockCopy将ushort[]转为int[]出现异常值问题求助

问题原因

Buffer.BlockCopy 是按原始字节直接复制的,它不会做任何类型转换或字节扩展:

  • ushort 每个元素占2字节,你的源数组总字节数是 4096 * 4096 * 2 = 32768000 字节
  • int 每个元素占4字节,目标数组要容纳相同数量的元素,需要 4096 * 4096 * 4 = 65536000 字节

直接用 Buffer.BlockCopy 复制时,每个int元素只会被填充前2字节(来自ushort的值),剩下的2字节是内存中的随机垃圾数据。这些随机高位字节如果触发int的符号位(int最高位为符号位),就会产生你看到的异常正负大数值。

解决方法

1. 循环赋值(JIT自动优化,性能足够)

直接遍历数组逐个转换,.NET的JIT会对这类简单循环做优化,实际执行速度并不慢:

ushort[] source = ...; // 你的4k*4k数组
int[] target = new int[source.Length];

for (int i = 0; i < source.Length; i++)
{
    target[i] = source[i]; // 隐式转换ushort到int,自动填充高位为0
}

2. SIMD批量转换(极致性能方案)

利用SIMD指令批量处理,适合追求最高性能的场景:

using System.Numerics;
using System.Runtime.InteropServices;

ushort[] source = ...;
int[] target = new int[source.Length];

ReadOnlySpan<ushort> sourceSpan = source.AsSpan();
Span<int> targetSpan = target.AsSpan();

int vectorSize = Vector<ushort>.Count;
int i = 0;

// 批量处理,利用SIMD加速转换
for (; i <= sourceSpan.Length - vectorSize; i += vectorSize)
{
    Vector<ushort> ushortVec = sourceSpan.Slice(i, vectorSize).Read<Vector<ushort>>();
    Vector<int> intVec = Vector.AsVectorInt32(ushortVec);
    intVec.CopyTo(targetSpan.Slice(i, vectorSize));
}

// 处理剩余的零散元素
for (; i < sourceSpan.Length; i++)
{
    targetSpan[i] = sourceSpan[i];
}

注意:禁用错误的字节解释方案

MemoryMarshal.Cast<ushort, int> 同样是按字节重新解释内存,会和Buffer.BlockCopy产生完全一样的异常值,本质是把2字节的ushort当作4字节的int读取,绝对不能用。

内容的提问来源于stack exchange,提问作者Евгений Федоров

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:01:09