допустим есть массив -999 0 -9 -1 2 3 -1
Как из него получить битовое представление 0100110 Или хотя бы Байтное.
var r = new Random(1);
int n = 100_000_000;
float[] arr = Enumerable.Range(0, n).Select<int, float>(e => r.NextSingle() * 2f - 1f).ToArray();
byte[]arrBytes = new byte[arr.Length];
{
for (int i = 0; i < n; i++)
{
if (arr[i] >= 0)
arrBytes[i] = 0;
else
arrBytes[i] = 1;
}
}
{
for (int i = 0; i < n; i++)
{
arrBytes[i]=((byte)(1 - (BitConverter.SingleToInt32Bits(arr[i]) >>> 31)));
}
}
'Как сделать векторизованное SIMD с Avx2 решение задачи из кода выше
Примерно как-то так, но как убрать последний цикл, и заменить его Avx операцией,
int len = Vector256<float>.Count;
for (int i = 0; i < n; i+= len)
{
var inputVector = Vector256.LoadUnsafe<float>(ref arr[i]);
var result = Vector256.ShiftRightLogical(inputVector.AsInt32(), 31);
for (int t = 0; t < len; t++)
{
arrBytes[i + t] =1- (byte)result[t];
}
}
К примеру 1 версия работает в 5-10 раз дольше чем ниже, этот должен еще в раза 4 по идеи работать,
Если кому интересно сделал вот так, очень страшное извлечение адреса, ради копирования. Но так быстрее. Кастомный метод CopyTo ломает алгоритм
int len = Vector128<float>.Count;
byte[] arrMasks = {
0,4,8,12
};
Vector128<byte> mask = Vector128.LoadUnsafe<byte>(ref arrMasks[0]);
for (int i = 0; i < n; i += len)
{
var inputVector = Vector128.LoadUnsafe<float>(ref arr[i]);
var result = Vector128.ShiftRightLogical(inputVector.AsInt32(), 31);
var res = (Avx2.Shuffle(result.AsByte(), mask));
void*ptr=Unsafe.AsPointer<Vector128<byte>>(ref res);
int* ptrInt=(int*)Unsafe.Add<byte>(ptr, 0);
var p = (int*) Unsafe.AsPointer<byte>(ref arrBytes[i]);
*p = *ptrInt;
}
Бенчмарк, там соотношение
15
2.6
1
в 15 раз разница .