Давно хотел посмотреть, как на деле обстоят дела с потоковой обработкой данных в .NET. И вот сегодня представился случай.
Код: недописанный класс, реализующий MD5. Использовался только один оператор для первого раунда (то, что в референсной реализации называется FF()).
using System;
using CryptoLib.Hashing;
using Mono.Simd;
namespace Test
{
    internal class Program
    {
        private static void Main()
        {
            var md5 = new Md5();
            const uint a = 1;
            const uint b = 2;
            const uint c = 3;
            const uint d = 4;
            var s = new Vector4ui(a, b, c, d);
            var x = new uint[16];
            uint r1 = md5.Op1(x, a, b, c, d, 0, 12, 0);
            Vector4ui r2 = md5.Op1(x, s, 0, 12, 0);
            const uint cycles = 100000000;
            DateTime st = DateTime.Now;
            for (uint i = 0; i < cycles; i++)
                r1 = md5.Op1(x, r1, b, c, d, 0, 12, 0);
            DateTime e1 = DateTime.Now;
            for (uint i = 0; i < cycles; i++)
                r2 = md5.Op1(x, r2, 0, 12, 0);
            DateTime e2 = DateTime.Now;
            int bits = IntPtr.Size*8;
            int ms1 = (e1 - st).Milliseconds;
            int ms2 = (e2 - e1).Milliseconds;
            Console.WriteLine("Running {0}-bit code.", bits);
            Console.WriteLine("Normal: {0}ms", ms1);
            Console.WriteLine("SIMD: {0}ms", ms2);
        }
    }
}
Реализация Md5.Op1() вовсе не замысловата:
public uint Op1(uint[] x,
                uint a, uint b, uint c, uint d,
                byte k, byte s, byte i)
{
    return b + (a + F(b, c, d) + x[k] + T[i]).Rol(s);
}
public Vector4ui Op1(uint[] x, Vector4ui state, byte k, byte s, byte i)
{
    state.X = state.Y + (state.X + F(state.Y, state.Z, state.W) + x[k] + T[i]).Rol(s);
    return state;
}
Среда выполнения:
- 64-битная Windows 7 RC (build 7100);
- Core2 Quad Q6600 (поддержка инструкций до SSSE3);
- .NET Framework CLR v2.0.50727;
- Mono 2.4 (под Windows есть только 32-битный CLR).
Результаты по трём запускам релизного кода:
| Normal (ms) | SIMD (ms) | Runtime | Bitness | 
| 331,33 | 11,33 | Mono+ | 32 | 
| 320,33 | 131,33 | Mono- | 32 | 
| 857,33 | 768,67 | MS .NET | 32 | 
| 853,67 | 774,00 | MS .NET | 64 | 
- Mono+ – с включенной оптимизацией (-O=simd);
- Mono- – с выключенной оптимизацией (-O=-simd).

Leave a Reply