SoFCheck
38 subscribers
64 links
Заметки по поводу разработки шахматного движка SoFCheck

Репозитории:
https://github.com/alex65536/sofcheck
https://github.com/alex65536/sofcheck-engine-tester
https://github.com/alex65536/sofcheck-weights-tuning
Download Telegram
Увы, я обнаружил, что в 15 августа SoFCheck на Lichess'е ничего не играл, потому что lichess-bot упал. Я его переподнял и настроил себе алерты, чтобы в следующий раз узнать о падении более оперативно

UPD: завел баг-репорт по мотивам прошлого падения
😢1
Интересный факт: GitHub умеет парсить Cargo.toml для Rust и понимать, кто использует какие репозитории в качестве зависимостей. Так я узнал, что у моего owlchess появились пользователи, кроме меня :) Первому пользователю я вручил pull request с исправлениями, которые делают использование owlchess более простым и идиоматичным
👍2
Пока с SoFCheck не происходит ничего нового. Но у меня появился второй канал @gepardchan, в котором я рассказываю про все остальное

Подписывайтесь :)
👍1
SoFCheck pinned «Пока с SoFCheck не происходит ничего нового. Но у меня появился второй канал @gepardchan, в котором я рассказываю про все остальное Подписывайтесь :)»
SoFCheck
Хорошая новость: теперь с SoFCheck'ом можно сразиться на Lichess :)
Я временно остановил бота на Lichess. Возможно, я через какое-то время найду ему новую виртуалку и запущу опять, но пока что будет так.

За все время работы (около 5.5 месяцев) SoFCheck наиграл 11'000 игр. Все эти партии сохранились, поэтому будет на что смотреть и на чем обучаться :)
🍾1
Потратил несколько дней на оптимизацию правил. В итоге практически никакого улучшения в силе игры не вышло: все улучшения либо ничего не давали, либо усиливали игру только на очень низком контроле времени (50мс на ход)

Оптимизации было три:
1) написать отдельный генератор для случая, когда мы под шахом. Идея в том, что в этом случае генерится очень много нелегальных ходов, и их количество хочется уменьшить. Это дает профит на маленьком контроле времени, поэтому я решил оставить
2) сейчас мы сначала делаем ход, а потом проверяем, что король не оказался под боем, и откатываем, если это не так. Получается, что на невалидный ход мы потратили много времени, потому что провернули moveMake() и moveUnmake(). Хотелось сначала проверять, не окажется ли король под шахом, а после этого делать ход. Эта оптимизация тоже не полетела, и я ее решил не вливать. Хотя на бенчмарках результаты такие же, как и без нее
3) при проверке на шах можно сразу проверить, что слона, ладьи или ферзя нет на одной линии с королем и не делать более дорогостоящие проверки. Это хорошо ведет себя на бенчмарках и на играх с контролем в 50мс на ход, но на большем контроле ничего не заметно

Параллельно оптимизации 2) и 3) поехали в owlchess (шахматную библиотеку на Rust). Правда, там они показали себя на бенчмарках странно: на части позиций вышло улучшение, на части — ухудшение :(

В общем, оптимизация генератора ходов — это не то место, где можно выбить большой плюс к рейтингу
🤔1
Я в последнее время занимался своей шахматной либой на Rust, а именно, пытался слегка прокачать ее перф. В итоге я лишь пришел к тому, что перестал понимать микробенчмарки ;(

Для бенчмарков, понятное дело, я использую criterion. С помощью него я измеряю время работы основных функций (генерация ходов, их валидация, применение, проверка на шах и т. д.) на десяти различных позициях. Каждая функция работает достаточно быстро: от 10 нс до 1 мкс.

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

При этом я:
1) Минимизировал влияние других программ и проводил бенчмарки даже без запущенной графической оболочки.
2) Перед запуском убрал динамическую частоту CPU, с помощью sudo cpupower frequency-set --governor performance.

Если кто-нибудь знает, почему так может быть и как с этим бороться — жду в комментариях :)
🤔2
SoFCheck
Я в последнее время занимался своей шахматной либой на Rust, а именно, пытался слегка прокачать ее перф. В итоге я лишь пришел к тому, что перестал понимать микробенчмарки ;( Для бенчмарков, понятное дело, я использую criterion. С помощью него я измеряю время…
Тем не менее, я немного поломал обратную совместимость и выпустил версию 0.4.0 :)

Основное изменение: теперь ход (который содержится в struct Move) содержит в себе походившую фигуру. Это позволяет лучше валидировать ход на самом раннем этапе (например, можно задолго до make_move проверить, что конь походил буквой Г или что слон походил по диагонали, а не на произвольное поле)
Решил написать шахматную библиотеку на Go:

https://github.com/alex65536/go-chess/tree/master

Battlefield тоже переписан теперь на Go и находится здесь:

https://github.com/alex65536/day20/tree/master/cmd/bfield

Более долгосрочный план — написать платформу, которая позволяет смотреть онлайн за сражениями шахматных движков. Чтобы это сделать, мне понадобилось легко запускать матчи между движками и отдавать по HTTP прогресс партии. Можно было, конечно, приспособить старый Battlefield на Паскале для этих целей, только надо разобраться, как в нем посылать HTTP-запросы по сети. Это реально, но я решил, что давно я не переписывал код с нуля лучше иметь единый код для собственно сервера и компоненты, которая запускает движки, и поэтому переписал все необходимые части на Go.

Еще, пока я писал, понял, что задумывался над написанием реализации UCI куда дольше, чем когда я реализовывал тоже самое на Object Pascal в далеком 2016 году. Вероятно потому, что тогда мне и в голову не приходило думать про всякие проблемы вроде синхронизации и таймаутов при зависании. А при попытке реализовать UCI сейчас то и дело пришлось думать над тем, как прокинуть контексты и что делать в случае, если их отменят. Еще захотелось сделать так, чтобы в движок можно было направлять команды из разных горутин параллельно, и библиотека применяла их в каком-то порядке, но корректно :) Короче, реализация получилась несколько сложнее, но «правильнее»

А с реализацией собственно шахматных правил проблем не было, тем более, что там не надо думать про сложные concurrency штуки, а надо просто написать код, который делает вычисления. Здесь могу лишь отметить, что на бенчмарках реализация на Go раза в три медленее, чем аналогичная на C++ и Rust, что совпадает с моими представлениями о том, насколько CPU intensive код работает медленнее на Go.
👍2
И кстати да, платформа для сражений шахматных движков будет называться day20 (как заметно по названию репы). Почему — говорить не буду, но небольшая подсказка есть в описании репы ;)