Оптимизация шахмат

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

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

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

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

Ответы

Ответ 1

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

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

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

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

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

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

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

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

Поиск повышения производительности

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

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

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

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

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

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

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

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

Ответ 2

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

Предполагая, что у вас уже есть рабочая таблица транспозиций.

Позднее уменьшение перемещения. Это дало моей программе около 100 эло-очков, и ее очень просто реализовать.

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

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

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

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

Наиболее важными частями поиска являются: Null Move Pruning, Check Extension и Late Move уменьшение.

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

Ответ 3

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

Ответ 4

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

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

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

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

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

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

Ответ 5

Хороший порядок перемещения!

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

Перенос заказов на порядок

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

  • Таблица транспонирования
  • Сортировка рекламных акций и хороших записей по их выигрышу.
  • Убийца движется
  • Перемещает этот результат на проверку противнику
  • История эвристики
  • Тихие перемещения - сортировка по значению PSQT

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

О Java/С# vs C/С++/Assembly

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

  • Таблица транспонирования
  • Открытие книги
  • Основы игровых столов
  • Улучшенная оценка статической платы для узлов листа
  • Биты для скорости Raw

Ответ 9

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

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

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

Ответ 10

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

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

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

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

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

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

  • Вы реализовали протокол 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 ЭЛО.

Ответ 11

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

Ответ 12

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

Я не уверен, что бы вы хотели узнать, но...