Небезопасно. Начиная с массива byte до ulong array
В настоящее время я смотрю на перенос моего metro hash implementon для использования функций С# 7, так как несколько частей могут получить прибыль от локальных ссылок повысить производительность.
Хэш выполняет вычисления в массиве ulong[4]
, но результатом является массив 16 byte
. В настоящее время я копирую массив ulong
в буфер результата byte
, но это занимает немного времени.
Поэтому мне интересно, можно ли System.Runtime.CompilerServices.Unsafe
использовать здесь:
var result = new byte[16];
ulong[] state = Unsafe.As<byte[], ulong[]>(ref result);
ref var firstState = ref state[0];
ref var secondState = ref state[1];
ulong thirdState = 0;
ulong fourthState = 0;
Вышеприведенный фрагмент кода означает, что я использую буфер результатов также для частей моих вычислений состояния, а не только для окончательного вывода.
Мои юнит-тесты успешны, и в соответствии с тестом benchmarkdotnet, пропускающим копию блока, это приведет к увеличению производительности 20%, что достаточно для меня, чтобы выяснить, правильно ли использовать его.
Ответы
Ответ 1
С# поддерживает "фиксированные буферы", вот что мы можем сделать:
public unsafe struct Bytes
{
public fixed byte bytes[16];
}
затем
public unsafe static Bytes Convert (long[] longs)
{
fixed (long * longs_ptr = longs)
return *((Bytes*)(longs_ptr));
}
Попробуйте. (1D массивы примитивных типов в С# всегда хранятся как непрерывный блок памяти, поэтому прием адреса массивов (управляемых) в порядке).
Вы также можете вернуть указатель для большей скорости:
public unsafe static Bytes * Convert (long[] longs)
{
fixed (long * longs_ptr = longs)
return ((Bytes*)(longs_ptr));
}
и манипулировать/обращаться к байтам, как вы хотите.
var s = Convert(longs);
var b = s->bytes[0];