Шахматные Оптимизации - PullRequest
20 голосов
/ 10 июля 2009

хорошо, так что я некоторое время работаю над своей шахматной программой, и я начинаю ударяться о стену. я выполнил все стандартные оптимизации (negascout, итеративное углубление, ходы убийцы, эвристический анализ истории, поиск покоя, оценка позиции пешки, некоторые расширения поиска) и у меня нет идей!

В скором времени я хочу сделать его многопоточным, и это должно дать мне хороший прирост производительности, но кроме этого есть еще какие-нибудь изящные трюки, с которыми вы, ребята, сталкивались? Я подумал о переходе на MDF (f), но я слышал, что это хлопотно и не стоит.

что меня больше всего интересует, так это какой-то алгоритм обучения, но я не знаю, делал ли кто-нибудь это эффективно с шахматной программой.

также, будет ли значительным переход на битовую плату? В настоящее время я использую 0x88.

Ответы [ 12 ]

24 голосов
/ 13 июля 2009

За последний год разработки моего шахматного движка ( www.chessbin.com ) большая часть времени была потрачена на оптимизацию моего кода, чтобы обеспечить более быстрый и быстрый поиск по ходу. За это время я выучил несколько трюков, которыми хотел бы поделиться с вами.

Измерение производительности

По сути, вы можете улучшить свою производительность двумя способами:

  • Оцените ваши узлы быстрее
  • Поиск меньшего количества узлов, чтобы придумать тот же ответ

Ваша первая проблема в оптимизации кода будет измерение. Откуда вы знаете, что вы действительно изменили ситуацию? Чтобы помочь вам с этой проблемой, вам необходимо убедиться, что вы можете записать некоторую статистику во время поиска ходов. Те, что я запечатлел в своем шахматном движке:

  • Время, необходимое для поиска полный.
  • Количество найденных узлов

Это позволит вам сравнить и протестировать ваши изменения. Лучший способ приблизиться к тестированию - создать несколько сохраненных игр из начальной позиции, средней игры и конечной игры. Запишите время и количество найденных узлов для черно-белых изображений. После внесения каких-либо изменений я обычно выполняю тесты с вышеупомянутыми сохраненными играми, чтобы увидеть, добился ли я улучшения в двух вышеупомянутых матрицах: число найденных узлов или скорость.

Чтобы усложнить ситуацию, после изменения кода вы можете запустить свой движок 3 раза и каждый раз получать 3 разных результата. Допустим, ваш шахматный движок нашел лучший ход за 9, 10 и 11 секунд. Это спред около 20%. Так вы улучшили свой движок на 10% -20% или это была просто измененная нагрузка на ваш компьютер? Откуда вы знаете? Чтобы бороться с этим, я добавил методы, которые позволят моему движку играть против себя, он будет делать ходы как для белых, так и для черных. Таким образом, вы можете проверить не только разницу во времени за один ход, но и серию из 50 ходов в течение игры. Если в прошлый раз игра занимала 10 минут, а теперь - 9, вы, вероятно, улучшили свой двигатель на 10%. Повторное выполнение теста должно подтвердить это.

Поиск прироста производительности

Теперь, когда мы знаем, как измерять прирост производительности, давайте обсудим, как определить потенциальный прирост производительности.

Если вы находитесь в среде .NET, то .NET Profiler будет вашим другом. Если у вас есть выпуск Visual Studio для разработчиков, он поставляется бесплатно, однако есть и другие сторонние инструменты, которые вы можете использовать. Этот инструмент сэкономил мне часы работы, поскольку он подскажет вам, где ваш двигатель проводит большую часть своего времени, и позволит вам сосредоточиться на проблемных местах. Если у вас нет инструмента профилирования, вам, возможно, придется каким-то образом регистрировать метки времени, поскольку ваш движок проходит через различные этапы. Я не предлагаю это. В этом случае хороший профилировщик на вес золота. Red Gate ANTS Profiler - дорогой, но лучший из тех, что я когда-либо пробовал. Если вы не можете себе этого позволить, хотя бы используйте его на 14-дневную пробную версию.

Ваш профилировщик определит вещи для вас, однако вот несколько небольших уроков, которые я усвоил, работая с C #:

  • Сделай все приватнее
  • Что бы ты не делал приватным, сделай это запечатано
  • Сделать столько методов статичными, сколько возможно.
  • Не делайте ваши методы болтливыми, один длинный метод лучше чем 4 меньше из них.
  • Шахматная доска хранится в виде массива [8] [8] медленнее, чем массив [64]
  • Замените int байтом, где это возможно.
  • Вернитесь из своих методов уже в возможно.
  • Стеки лучше списков
  • Массивы лучше, чем стеки и списки.
  • Если вы можете определить размер список, прежде чем его заполнить.
  • Кастинг, бокс, распаковка - зло.

Дальнейшее повышение производительности:

Iнайти генерацию ходов и порядок чрезвычайно важны. Однако вот проблема, как я ее вижу. Если вы оцените счет каждого хода перед тем, как сортировать и запускать альфа-бета-версию, вы сможете оптимизировать порядок своих ходов таким образом, чтобы получить чрезвычайно быстрые отсечки альфа-бета-версии. Это потому, что вы в первую очередь сможете попробовать лучший ход. Однако время, потраченное на оценку каждого хода, будет потрачено впустую. Например, вы могли оценить счет за 20 ходов, отсортировать свои ходы, попробовать первые 2 и получить отсечение на ходу номер 2. Теоретически время, которое вы потратили на остальные 18 ходов, было потрачено впустую.

С другой стороны, если вы выполняете более легкую и намного более быструю оценку, скажем, просто захватывает, ваш вид не будет таким хорошим, и вам придется искать больше узлов (до 60% больше). С другой стороны, вы не будете делать тяжелую оценку на каждом возможном шаге. В целом этот подход обычно быстрее .

Нахождение этого идеального баланса между наличием достаточного количества информации для хорошей сортировки и отсутствием дополнительной работы с ходами, которые вы не будете использовать, позволит вам найти огромный выигрыш в вашем алгоритме поиска. Кроме того, если вы выберете подход с более плохой сортировкой, вам нужно сначала выполнить более мелкий поиск, скажем, сгиб 3, отсортировать ваш ход, прежде чем углубляться в поиск (это часто называется итеративным углублением). Это значительно улучшит ваш вид и позволит вам искать гораздо меньше ходов.

5 голосов
/ 05 октября 2009

Отвечая на старый вопрос.

Если у вас уже есть рабочий стол транспонирования.

Сокращение позднего хода. Это дало моей программе около 100 очков, и ее очень легко реализовать.

По моему опыту, если ваша реализация не очень неэффективна, то фактическое представление платы (0x88, битовая плата и т. Д.) Не так уж важно.

Хотя вы можете нанести вред своему шахматному движку с плохой производительностью, сам по себе генератор молниеносного хода сам по себе не сделает программу хорошей.

Используемые уловки поиска и функция оценки являются определяющими факторами, определяющими общую силу.

И, безусловно, наиболее важными частями оценки являются материал, пройденные пешки, безопасность короля и структура пешки.

Наиболее важными частями поиска являются: обрезка нулевого хода, проверка расширения и уменьшение позднего перемещения.

Ваша программа может пройти долгий и длинный путь только на этих простых приемах!

3 голосов
/ 24 июня 2015

Хороший порядок ходов!

Старый вопрос, но сейчас применяются те же методы, что и 5 лет назад. Разве мы не все пишем свои собственные шахматные движки, у меня есть свой собственный, называемый «норвежский гамбит», который, я надеюсь, в конечном итоге будет конкурировать с другими движками Java в CCRL. Я, как и многие другие, использую Stockfish для идей, потому что он так хорошо написан и открыт. Их среда тестирования Fishtest и ее сообщество также дают массу полезных советов. Стоит сравнить ваши оценочные баллы с тем, что получает Stockfish, поскольку то, как оценивать, является, вероятно, самым большим неизвестным в шахматном программировании, и Stockfish отошел от многих традиционных уловок, которые стали городскими легендами (например, бонус двойного слона). Однако самое большое различие заключалось в том, что после того, как я применил те же методы, что и вы, Negascout, TT, LMR, я начал использовать Stockfish для сравнения и заметил, что на той же глубине Stockfish искали гораздо меньше ходов, чем я (из-за порядка перемещения ).

Переместить основы заказа

Одна вещь, которую легко забыть, это хороший порядок ходов. Для того, чтобы отсечение Альфа-беты было эффективным, важно сначала получить лучшие ходы. С другой стороны, это также может занять много времени, поэтому важно делать это только по мере необходимости.

  1. Стол транспонирования
  2. Сортировка рекламных акций и удачных снимков по их выигрышу
  3. Убийственные ходы
  4. Ходы, которые приводят к проверке противника
  5. История эвристики
  6. Тихие ходы - сортировка по значению PSQT

Сортировка должна выполняться по мере необходимости, обычно достаточно отсортировать перехваты, и после этого можно выполнить более дорогую сортировку чеков и PSQT только при необходимости.

О Java / C # против C / C ++ / Assembly

Методы программирования для Java те же, что и в отличном ответе Адама Берента, который использовал C #. В дополнение к его списку я бы упомянул, что нужно избегать массивов объектов, а использовать множество массивов примитивов, но, вопреки его предложению использовать байты, я считаю, что с 64-битной java мало что можно сохранить, используя byte и int вместо 64-битной длины. Я также прошел путь переписывания на C / C ++ / Assembly, и у меня нет никакого прироста производительности вообще. Я использовал ассемблерный код для инструкций битового сканирования, таких как LZCNT и POPCNT, но позже я обнаружил, что Java 8 также использует их вместо методов объекта Long. К моему удивлению, Java работает быстрее, кажется, что виртуальная машина Java 8 работает лучше, чем компилятор C.

2 голосов
/ 21 декабря 2009

Это довольно старый вопрос, я просто искал вопросы по шахматам и нашел этот вопрос без ответа. Что ж, сейчас это может вам не помочь, но может оказаться полезным для других пользователей.

Я не видел обрезку нулевого хода, таблицы транспонирования ... вы их используете? Они дадут вам большую поддержку ...

Одна вещь, которая дала мне большой импульс, - это минимизация условного ветвления ... Многое можно вычислить заранее. Поиск таких возможностей.

Большинство современных ПК имеют несколько ядер, поэтому было бы неплохо сделать их многопоточными. Вам не обязательно идти MDF (F) для этого.

Я не рекомендую переносить ваш код на битборд. Это просто слишком много работы. Несмотря на то, что на 64-битных компьютерах битборды могут дать импульс.

Наконец, и самое главное, шахматная литература доминирует над любой оптимизацией, которую мы можем использовать. оптимизация - это слишком много работы. Посмотрите на шахматные движки с открытым исходным кодом, особенно хитрые и фрукты / тогу. Фрукты изначально были с открытым исходным кодом.

2 голосов
/ 11 июля 2009

Имейте в виду, что поиск игр в многопоточной среде может быть непростой задачей ( Я пробовал ). Это может быть сделано, но из некоторого литературного поиска, который я сделал некоторое время назад, очень трудно получить какое-либо повышение скорости вообще.

2 голосов
/ 10 июля 2009

Я знаю об одном улучшении, о котором говорили на курсах ИИ в университете, где имеется огромная база данных завершающих ходов. Таким образом, наличие предварительно рассчитанной базы данных для игр с небольшим количеством оставшихся фигур. Таким образом, если вы нажмете на ближнем конце позиции в своем поиске, вы остановите поиск и примете заранее рассчитанное значение, которое улучшает результаты поиска, например дополнительное углубление, которое вы можете сделать для важных / критических ходов без больших затрат времени на вычисления. Я думаю, что это также связано с изменением эвристики в поздней стадии игры, но я не шахматист, поэтому я не знаю динамики окончания игры.

1 голос
/ 14 ноября 2016

Поздний ответ, но это может кому-то помочь:

Учитывая все упомянутые вами оптимизации, 1450 ELO очень низок. Я думаю, что что-то не так с вашим кодом. Ты сделал:

  1. Написал perft рутину и провел ее через ряд позиций? Все тесты должны пройти, так что вы знаете, что в вашем генераторе ходов нет ошибок. Если у вас этого нет, говорить об ELO бессмысленно.

  2. Написал mirrorBoard подпрограмму и провел пробный код через набор позиций? Результат должен быть одинаковым для обычной и зеркальной позиций, в противном случае у вас есть ошибка в вашем eval.

  3. Есть ли у вас хеш-таблица (или таблица транспонирования)? Если нет, то это обязательно. Это поможет при поиске и упорядочении ходов, что дает грубую разницу в скорости.

  4. Как вы реализуете порядок перемещения? Это ссылки на пункт 3.

  5. Реализовали ли вы протокол UCI? Ваша функция move parsing работает правильно? У меня в двигателе была такая ошибка:

      /* Parses a uci move string and return a Board object */
      Board parseUCIMoves(String moves)// e2e4 c7c5 g1f3 ...{
          //...
          if (someMove.equals("e1g1") || someMove.equals("e1c1"))
              //apply proper castle
         //...
     }
    

Иногда двигатель вылетал во время игры матча, и я думал, что это ошибка GUI, так как все тесты производительности были в порядке. Мне понадобилась одна неделя, чтобы найти ошибку по счастливой случайности. Итак, проверить все.

Для (1) вы можете искать каждую позицию до глубины 6. Я использую файл с ~ 1000 позиций. Смотрите здесь https://chessprogramming.wikispaces.com/Perft

Для (2) вам просто нужен файл с миллионами позиций (только строка FEN).

Учитывая все вышеперечисленное и очень простую функцию оценки (материал, квадратные столы, пройденные пешки, безопасность короля), он должен играть при + -2000 ELO.

1 голос
/ 10 июля 2009

Что касается советов, я знаю, что можно добиться больших успехов в оптимизации ваших подпрограмм генерации ходов перед любыми функциями eval. Если вы сделаете эту функцию максимально узкой, это может дать вам 10% или более улучшений в узлах в секунду.

Если вы переходите на битборды, покопайтесь в архивах компьютера rec.games.chess.com для некоторых старых сообщений доктора Роберта Хаятта о Крафти (уверен, что он больше не публикует). Или возьмите последнюю копию с его FTP и начните копать. Я уверен, что для вас это будет значительным изменением.

0 голосов
/ 25 декабря 2013

Профиль и ориентир. Теоретическая оптимизация хороша, но если вы не будете измерять влияние каждого изменения на производительность, вы не будете знать, улучшается ли ваша работа или ухудшает скорость финального кода.

Старайтесь ограничить себя штрафом за использование разных алгоритмов. Упростите тестирование различных реализаций алгоритмов друг против друга. то есть упростить создание версии кода для PVS, а также версии NegaScout.

Найдите горячие точки. Рефакторинг. Перепишите в сборке, если необходимо. Повторите.

0 голосов
/ 10 июля 2009
  • Таблица транспонирования
  • Вступительная книга
  • Конец игрового стола
  • Улучшенная оценка статической платы для узлов листа
  • Битборды для сырой скорости
...