Я пытаюсь использовать подход "оценщика рук RayW", чтобы получить оценку комбинации карт (5 лучших карт из 7 ). Однако у меня возникли некоторые проблемы с производительностью при использовании этого метода. Согласно источникам -, при таком подходе должно быть возможно оценить более 300 миллионов раздач в секунду! Мой результат — 10 миллов за 1,5 секунды, что в разы медленнее.
Идея «оценщика рук RayW» следующая:
Оценщик Two Plus Two состоит из большой таблицы поиска, содержащей около тридцати -двух миллионов записей (32 487 834, если быть точным ). Чтобы чтобы найти заданную покерную комбинацию из 7 -карт, вы прокладываете путь через этот table, выполняя один поиск на карточку. Когда вы дойдете до последней карты, полученное таким образом значение является официальным значением эквивалентности руки
вот как выглядит код:
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;
}
Я считаю, что этот метод изначально был реализован на C++, но тем не менее, порт C #должен работать быстрее.Есть ли способ приблизиться хотя бы к 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]];
}
Вот цитата:
После удаления "небезопасных" частей кода и небольших корректировок в версия c #теперь также составляет около 310 миллионов.
Есть ли другой способ повысить эффективность этой системы ранжирования рук?