すべての回答は 1 バイトのみを書き込んでいます。バイト配列に単語を入力したい場合はどうすればよいでしょうか。それとも浮きますか?私は時々それを使います。そのため、「memset」と同様のコードを一般的ではない方法で数回記述し、このページにたどり着いて単一バイトの適切なコードを見つけた後、以下のメソッドを記述しました。
PInvoke と C++/CLI にはそれぞれ欠点があると思います。そして、ランタイム 'PInvoke' を mscorxxx に入れてみませんか? Array.Copy と Buffer.BlockCopy は確かにネイティブ コードです。BlockCopy は「安全」でさえありません。long を別の途中までコピーしたり、配列内にある限り DateTime を超えてコピーしたりできます。
少なくとも、このようなことのために新しい C++ プロジェクトを提出するつもりはありません。それはほぼ確実に時間の無駄です。
基本的に、これは Lucero と TowerOfBricks によって提示されたソリューションの拡張バージョンであり、long、int など、およびシングルバイトを memset するために使用できます。
public static class MemsetExtensions
{
static void MemsetPrivate(this byte[] buffer, byte[] value, int offset, int length) {
var shift = 0;
for (; shift < 32; shift++)
if (value.Length == 1 << shift)
break;
if (shift == 32 || value.Length != 1 << shift)
throw new ArgumentException(
"The source array must have a length that is a power of two and be shorter than 4GB.", "value");
int remainder;
int count = Math.DivRem(length, value.Length, out remainder);
var si = 0;
var di = offset;
int cx;
if (count < 1)
cx = remainder;
else
cx = value.Length;
Buffer.BlockCopy(value, si, buffer, di, cx);
if (cx == remainder)
return;
var cachetrash = Math.Max(12, shift); // 1 << 12 == 4096
si = di;
di += cx;
var dx = offset + length;
// doubling up to 1 << cachetrash bytes i.e. 2^12 or value.Length whichever is larger
for (var al = shift; al <= cachetrash && di + (cx = 1 << al) < dx; al++) {
Buffer.BlockCopy(buffer, si, buffer, di, cx);
di += cx;
}
// cx bytes as long as it fits
for (; di + cx <= dx; di += cx)
Buffer.BlockCopy(buffer, si, buffer, di, cx);
// tail part if less than cx bytes
if (di < dx)
Buffer.BlockCopy(buffer, si, buffer, di, dx - di);
}
}
これがあれば、短いメソッドを追加して memset に必要な値の型を取得し、プライベート メソッドを呼び出すことができます。たとえば、このメソッドで ulong の置き換えを見つけるだけです。
public static void Memset(this byte[] buffer, ulong value, int offset, int count) {
var sourceArray = BitConverter.GetBytes(value);
MemsetPrivate(buffer, sourceArray, offset, sizeof(ulong) * count);
}
または、ばかげて、任意のタイプの構造体でそれを行います (ただし、上記の MemsetPrivate は、2 の累乗であるサイズにマーシャリングする構造体に対してのみ機能します)。
public static void Memset<T>(this byte[] buffer, T value, int offset, int count) where T : struct {
var size = Marshal.SizeOf<T>();
var ptr = Marshal.AllocHGlobal(size);
var sourceArray = new byte[size];
try {
Marshal.StructureToPtr<T>(value, ptr, false);
Marshal.Copy(ptr, sourceArray, 0, size);
} finally {
Marshal.FreeHGlobal(ptr);
}
MemsetPrivate(buffer, sourceArray, offset, count * size);
}
前に述べた initblk を変更して、コードとパフォーマンスを比較するために ulong を取得しましたが、それは黙って失敗しました。コードは実行されますが、結果のバッファーには ulong の最下位バイトのみが含まれます。
それにもかかわらず、for、initblk、および memset メソッドを使用して、大きなバッファーとして書き込むパフォーマンスを比較しました。バッファ長に収まる回数に関係なく、8 バイトの ulong を書き込む 100 回の繰り返しの合計時間はミリ秒です。for バージョンは、単一の ulong の 8 バイトに対して手動でループ展開されます。
Buffer Len #repeat For millisec Initblk millisec Memset millisec
0x00000008 100 For 0,0032 Initblk 0,0107 Memset 0,0052
0x00000010 100 For 0,0037 Initblk 0,0102 Memset 0,0039
0x00000020 100 For 0,0032 Initblk 0,0106 Memset 0,0050
0x00000040 100 For 0,0053 Initblk 0,0121 Memset 0,0106
0x00000080 100 For 0,0097 Initblk 0,0121 Memset 0,0091
0x00000100 100 For 0,0179 Initblk 0,0122 Memset 0,0102
0x00000200 100 For 0,0384 Initblk 0,0123 Memset 0,0126
0x00000400 100 For 0,0789 Initblk 0,0130 Memset 0,0189
0x00000800 100 For 0,1357 Initblk 0,0153 Memset 0,0170
0x00001000 100 For 0,2811 Initblk 0,0167 Memset 0,0221
0x00002000 100 For 0,5519 Initblk 0,0278 Memset 0,0274
0x00004000 100 For 1,1100 Initblk 0,0329 Memset 0,0383
0x00008000 100 For 2,2332 Initblk 0,0827 Memset 0,0864
0x00010000 100 For 4,4407 Initblk 0,1551 Memset 0,1602
0x00020000 100 For 9,1331 Initblk 0,2768 Memset 0,3044
0x00040000 100 For 18,2497 Initblk 0,5500 Memset 0,5901
0x00080000 100 For 35,8650 Initblk 1,1236 Memset 1,5762
0x00100000 100 For 71,6806 Initblk 2,2836 Memset 3,2323
0x00200000 100 For 77,8086 Initblk 2,1991 Memset 3,0144
0x00400000 100 For 131,2923 Initblk 4,7837 Memset 6,8505
0x00800000 100 For 263,2917 Initblk 16,1354 Memset 33,3719
initblk と memset の両方がヒットするため、毎回最初の呼び出しを除外しました。最初の呼び出しでは約 .22ms だったと思います。少し驚いたことに、私のコードは initblk よりも短いバッファーを埋める方が速く、ページの半分がセットアップ コードでいっぱいになっています。
誰かがこれを最適化したいと思うなら、本当に先に進んでください。それが可能だ。