2009-07-10 5 views
17

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

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

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

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

+0

Вы можете отредактировать свой пост (например, вопрос или ответ), чтобы добавить дополнительную информацию, подобную этой. Просто нажмите ссылку «Изменить» ниже сообщения. – balpha

+4

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

+1

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

ответ

-1

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

+0

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

+0

В таком случае, почему бы не использовать базу данных предыдущих ходов (например, игры с высоким профилем перемещаются в Интернете), классифицированные по навыкам, агрессии и т. Д., Что дает вам много ценных данных. – Draemon

+0

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

-2

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

Я не уверен, какой тип вещи вы хотели бы, чтобы узнать, однако ...

2

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

+0

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

1

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

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

0
  • Транспонирование Таблица
  • Книга Открытие
  • Конец игры Таблица Основы
  • Улучшение Статическая Совет по оценке конечных узлов
  • Bitboards для Raw Speed ​​
1

быть предупрежден, получение поиска игры право в резьбовой среде может быть королевская боль (I've tried it). Это можно сделать, но из некоторых литературных поисков, которые я сделал некоторое время назад, очень сложно добиться какого-либо повышения скорости.

22

За последний год разработки моего шахматного движка (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-дневной пробной версии.

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

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

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

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

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

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

+1

+1 удивительный ответ, но один маленький nitpick: 'Если вы можете определить размер списка, прежде чем его заполнить.' ... что? – RCIX

+2

Он, вероятно, имел в виду, что если вы можете определить размер заранее, вы должны. – jasonh

+0

Список = новый Список (100) –

4

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

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

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

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

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

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

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

Важнейшими частями поиска являются: Null Move Obning, Check Extension и Late Move reduction.

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

2

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

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

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

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

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

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

0

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

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

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

2

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

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

Перемещение заказа предметов первой необходимости

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

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

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

О Java/C# против C/C++/Сборка

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

0

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

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

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

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

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

  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, так как все perft тесты были в порядке. Мне понадобилась неделя, чтобы найти ошибку на удачу. Итак, проверить все.

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

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

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

Смежные вопросы