Я пытаюсь использовать подход оценки "RayW hand оценщик", чтобы получить оценку комбинации карт (5 лучших карт из 7). Однако с этим методом возникают проблемы с производительностью . Согласно источникам, используя этот подход, можно оценить более 300 мил в секунду! Мой результат составляет 10 мельниц за 1,5 секунды, что во много раз медленнее.
Идея "оценщика рук RayW" следующая:
Оценщик Two Plus Two состоит из большой таблицы поиска, содержащей около тридцати двух миллионов записей (точнее, 32 487 834). В порядке для поиска данной 7-карточной покерной руки, вы прослеживаете путь через этот стол, выполняющий один поиск на карту. Когда вы доберетесь до последней карты, полученное значение является официальным значением эквивалентности руки
вот как выглядит код:
namespace eval
{
public struct TPTEvaluator
{
public static int[] _lut;
public static unsafe void Init() // to load a table
{
_lut = new int[32487834];
FileInfo lutFileInfo = new FileInfo("HandRanks.dat");
if (!lutFileInfo.Exists)
{throw new Exception("Handranks.dat not found");}
FileStream lutFile = new FileStream("HandRanks.dat", FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096);
byte[] tempBuffer = new byte[32487834 * 4];
lutFile.Read(tempBuffer, 0, 32487834 * 4);
fixed (int* pLut = _lut)
{ Marshal.Copy(tempBuffer, 0, (IntPtr)pLut, 32487834 * 4);}
tempBuffer = null;
}
public unsafe static int LookupHand(int[] cards) // to get a hand strength
{
fixed (int* pLut = _lut)
{
int p = pLut[53 + cards[0]];
p = pLut[p + cards[1]];
p = pLut[p + cards[2]];
p = pLut[p + cards[3]];
p = pLut[p + cards[4]];
p = pLut[p + cards[5]];
return pLut[p + cards[6]];
}
}
}
}
и что я тестирую этот подход:
private void button4_Click(object sender, EventArgs e)
{
int[] str = new int[] { 52, 34, 25, 18, 1, 37, 22 };
int r1 = 0;
DateTime now = DateTime.Now;
for (int i = 0; i < 10000000; i++) // 10 mil iterations 1.5 - 2 sec
{ r1 = TPTEvaluator.LookupHand(str);} // here
TimeSpan s1 = DateTime.Now - now;
textBox14.Text = "" + s1.TotalMilliseconds;
}
Я считаю, что этот метод был первоначально реализован на С++, но, тем не менее, порт С# должен работать быстрее. Есть ли способ, каким образом я могу приблизиться хотя бы к 100 миллионам рук за одну секунду?
То, что я пробовал до сих пор:
- пытался использовать статические и нестатические методы - без разницы.
-
попытался использовать поиск словаря вместо массива
public void ArrToDict(int[] arr, Dictionary<int, int> dic) { for (int i = 0; i < arr.Length; i++) { dic.Add(i, arr[i]); } } public unsafe static int LookupHandDict(int[] cards) { int p = dict[53 + cards[0]]; p = dict[p + cards[1]]; p = dict[p + cards[2]]; p = dict[p + cards[3]]; p = dict[p + cards[4]]; p = dict[p + cards[5]]; return dict[p + cards[6]]; }
Истекшее время для 10 мельниц рук почти в 6 раз медленнее.
-
По словам одного человека - он увеличил производительность на 200 мельниц, удалив "небезопасный" код. Я попытался сделать то же самое, но результаты почти одинаковы.
public static int LookupHand(int[] cards) { int p = _lut[53 + cards[0]]; p = _lut[p + cards[1]]; p = _lut[p + cards[2]]; p = _lut[p + cards[3]]; p = _lut[p + cards[4]]; p = _lut[p + cards[5]]; return _lut[p + cards[6]]; }
Вот цитата:
После удаления "небезопасных" частей кода и небольших корректировок в версия С# теперь также составляет около 310 млн.
Есть ли другой способ повысить производительность этой системы ранжирования рук?