我有一个巨大的byte[] data
数组。我想采用特定的字节数(考虑为Blocksize
)并对其进行一些操作,并在新数组中一个接一个地添加每个块的所有结果。
这是我的代码:
int j = 0;
int number_of_blocks = (data.Length) / 16;
byte[] one_block = new byte[16];
byte[] one_block_return = new byte[16];
byte[] all_block_return = new byte[data.Length];
for (int i = 0; i < number_of_blocks; i++)
{
Array.Copy(data, j, one_block, 0, 16);
one_block_return = one_block_operation(one_block);
Array.Copy(one_block_return, 0, all_block_return, j, 16);
Array.Clear(one_block, 0, one_block.Length);
j = j + 16;
}
此代码的唯一问题是它太慢,因为我的数据数组非常大。所以我期待更换Array.Copy(),这比这更快,或者有人有更好的方法来做到这一点。我想知道有多少方法可以做到这一点,并希望看到编码的变化。
-Thanks
答案 0 :(得分:1)
简单并行化怎么样?
int number_of_blocks = (int)Math.Ceiling((double)data.Length / 16);
byte[] all_block_return = new byte[data.Length];
Parallel.For(0, number_of_blocks - 1, block_no =>
{
var blockStart = block_no * 16; // 16 - block size
var blockLength = Math.Min(16, data.Length - blockStart);
byte[] one_block = new byte[16];
byte[] one_block_return = new byte[16];
Array.Copy(data, blockStart, one_block, 0, blockLength);
one_block_return = one_block_operation(one_block);
Array.Copy(one_block_return, 0, all_block_return, blockStart, blockLength);
});
有可能将one_block_operation
用data, blockStart, blockStart + blockLength
个参数代替缓冲区(one_block
)?您可以避免Array.Copy
之一。
修改强> 下面是它的工作原理: 首先,我们需要计算数量或块。然后使用指定的参数执行Parallel.For:start index,end index和传递一个参数的委托 - 当前处理的索引。在我们的例子中,索引被认为是块数。相当于此代码的是:
for (var block_no = 0, block_no <= number_of_blocks - 1; block_no++) {
delegate(block_no);
}
唯一的区别是 Parallerl.For
在多个线程中运行该循环。线程计数不固定 - 它取决于ThreadPool大小(根据MSDN,它还取决于许多因素)。
由于每个deletage都可以独立调用(我们不知道调用deletagtes的顺序)我们不能使用变量来存储deletegate之外的当前块启动索引(就像你将它存储在for循环外)。但是如果我们知道块的当前块数和大小,那么计算块起始索引非常容易(并且在第8行完成)。
不 - 你不能跳过第9行或用const值16替换它。为什么?考虑以下顺序:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
我们可以将这个序列分成两个大小为16的块: 第1名:[1-16] 第二名:[17]
所以,就像你看到的那样 - 第二个块不包含16个元素,但只有1.第9行计算实际块大小/长度,因此你可以轻松避免IndexOutOfBoundException。