我有这个字节数组:
byte[,,] somedata = new byte[100,150,3];
~somedata is now populated by an external input.
我只想在其中使用这些值:
byte[,] useThisDataOnly = new byte[100,150];
目前,我使用这个:
foreach (int x=0,x< 100; x++)
{
foreach (int y=0,y< 150; y++)
{
useThisDataOnly [x,y] = somedata[x,y,0];
}
}
有没有更快的方法可以做到这一点?
另外,我将把这个useThisDataOnly扁平化(据我所知,它的处理速度更快)。
有什么建议?
优化这一点的困难在于,要忽略的字节位于最“快速移动”的索引中。
我的意思是:如果像这样将连续的数字分配给每个数组元素:
byte[,,] source = new byte[100, 150, 3];
for (int i = 0, n = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
for (int k = 0; k < 3; ++k, ++n)
source[i, j, k] = unchecked ((byte)n);
如果按展平的顺序打印内容,将得到0..255重复。
然后,您排除最终尺寸:
for (int i = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
dest[i, j] = source[i, j, 0];
如果按展平的顺序打印结果,将得到:
0, 3, 6, 9, 12, 15, ...
因此,您可以看到为了将输入转换为输出,您需要占用每个第三个字节,但是不幸的是,没有快速的方法可以做到这一点。
但是,如果您能够要求创建的数组首先要省略索引:
byte[,,] source = new byte[3, 100, 150];
这样您就可以使用了Buffer.BlockCopy()
。
我猜这不是一个选择-否则,手工编码的循环可能是最快的方法,而无需求助于不安全的代码。
不安全的代码
这是使用不安全的代码和指针的方法。这甚至可能无法使其更快,因此在选择执行此操作之前,您需要(a)确保执行简单的方法确实太慢,并且(b)对发布版本的使用Stopwatch
进行一些仔细的计时以确保它确实值得使用不安全的代码。
还应注意使用不安全代码的弊端!不安全的代码需要提升的权限,并且可能导致您的程序因低级C ++风格的野生指针错误而崩溃!
using System;
using System.Diagnostics;
namespace Demo
{
internal static class Program
{
static void Main()
{
byte[,,] source = new byte[100, 150, 3];
for (int i = 0, n = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
for (int k = 0; k < 3; ++k, ++n)
source[i, j, k] = unchecked ((byte)n);
byte[,] dest1 = new byte[100, 150];
byte[,] dest2 = new byte[100, 150];
for (int i = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
dest1[i, j] = source[i, j, 0];
unsafe
{
fixed (byte* sp = source)
fixed (byte* dp = dest2)
{
byte* q = dp;
byte* p = sp;
for (int i = 0; i < 100*150; ++i)
{
*q++ = *p;
p += 3;
}
}
}
for (int i = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
Trace.Assert(dest1[i, j] == dest2[i, j], "Arrays should be identical");
}
}
}
我个人认为使用简单,安全的循环不会太慢,但是现在至少您可以尝试一些代码。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句