使用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,提问作者Евгений Федоров
相关产品推荐
相关产品推荐

