Чему научился:
Это будет длинный отчёт, но, надеюсь, интересный!
В общем я решил заморочиться и сделать много ненужной работы! Опытным путём удалось выяснить, что очень большие потери идут на пересоздание board, но как уменьшить расходы на пересоздание, чтобы при этом не сбивалось расположение фигур я пока не придумал.
Тогда я подумал, как можно ускорить расчёты и решил распараллелить метод Program.NextMoves(). Сделать по-уму через Parallels.Foreach вначале не получилось, так как получались неверные результаты, и тогда я решил схитрить и сделать через PLINQ, а заодно потестить и простой LINQ. Вначале результаты были обнадёживающие, но после нескольких тестовых запусков пошли неверные результаты в многопотоке и тогда я всё-таки разобрался, как сделать многопоточный foreach. Ещё я попытался распараллелить метод Chess.YieldValidMoves(), но из этого ничего хорошего не вышло. Точнее, все распараллеливания считали быстро, но считали ерунду :)
В ходе тестирования выяснилось также, что просто перевод foreach в LINQ иногда быстрее. В общем я провёл следующее тестирование: NextMoves - простой метод из урока, NextMovesLINQ - он же, но преобразованный в LINQ, NextMovesParallel - реализованный через Parallel.Foreach Этими методами я вызывал следующие методы: YieldValidMoves - метод из Chess, стостоящий из лесенки foreach, YieldValidMovesLINQ - он же, но преобразованный в LINQ
Результаты, полученные на моём ноутбуке с процессором i5 8250 для стартового FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1":
Выводы: 1) Распараллеливание вредно для глубины просчёта 1, но очень полезно начиная с 2 и далее. 2) Использование LINQ в обоих методах для глубины 1 даёт наибольшую скорость расчётов. 3) Начиная с глубины просчёта 2 распараллеливание очень ускоряет расчёты. 4) Использование распараллеливания в первом методе для глубины 2 и 3 совместно с LINQ во втором методе в целом даёт наибольший эффект, за исключением NextMovesLINQ() + YieldValidMovesLINQ() для глубины 2. 5) Совместное использование NextMovesLINQ() + YieldValidMovesLINQ(), а также NextMovesParallel() + YieldValidMovesLINQ() в глубине расчётов 4 начинает немного отставать от связок NextMovesLINQ() + YieldValidMoves() и NextMovesParallel() + YieldValidMovesLINQ().
Это результат одного из прогонов теста на "прогретом" процессоре. Конечно на малой глубине просчётов были заметные колебания во времени исполнения, но я не стал собирать базу прогонов и вычислять средние значения. Но "на глаз" значения в среднем такие и получаются.
Баги: 1) В одном запуске из примерно 5 на глубине 1, несмотря на использование блокировки потоков связка NextMovesParallel() + YieldValidMoves() давало результат 21. 2) В одном запуске из примерно 3 на глубине 1, просто использование связки NextMovesParallel() + YieldValidMovesLINQ() давало результат 21 или 22. 3) На глубине просчётов выше 2 ошибок не замечено.
Для других стартовых позиций я подробно быстродействие не тестировал, только проверил на соответствие верным результатам. Ошибки были только во второй стартовой позиции на сайте из шести: "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R". Так как в остальных 5 позициях всё было верно (за исключением лишней 1 или 2 при многопоточности на малой глубине), то, вероятно причина в том, что в коде не учитываются особые патовые ситуации.
Что было сложным:
Заставить *почти* без ошибок работать распараллеливание.
Только сейчас заметил: в Выводах пункт 5 в самом последнем слове-названии метода случайно дописал LINQ. Конечно должно быть так:
5) Совместное использование NextMovesLINQ() + YieldValidMovesLINQ(), а также NextMovesParallel() + YieldValidMovesLINQ() в глубине расчётов 4 начинает немного отставать от связок NextMovesLINQ() + YieldValidMoves() и NextMovesParallel() + YieldValidMoves().
Впрочем, это и так из таблицы понятно было, так что думаю вряд-ли кто так внимательно читал отчёт, чтобы запутаться :)
Отчёт оценивали: 6452. Кирилл Шмойлов+1791. Валерий Жданов+15394. Anton+13922. Александр+117947. Dmitry Sinitsin+117443. WildOrc+19980. Timoha+110558. Иван Воронин+19858. Александр+13747. Сергей+116218. Дмитрий+110717. OloloCode+19971. Юрий+110895. Danil42Russia+14753. Андрей+117606. Виктор+1Посетитель+11. Евгений Волосатов+14395. Денис+16644. valerys Nikola+116066. Bodrik_torf+1Посетитель+1Посетитель+1459. Сергей Сергеевич+1
Начинаем практику по языку C#
Чтобы стать хорошим программистом — нужно писать программы.
На нашем сайте очень много практических упражнений.
После заполнения формы ты будешь подписан на рассылку
«C# Вебинары и Видеоуроки»,
у тебя появится доступ к видеоурокам и консольным задачам.
Несколько раз в неделю тебе будут приходить письма —
приглашения на вебинары, информация об акциях и скидках,
полезная информация по C#.
Научился: Проходить супер тест. Трудности: Найти места в коде откуда можно считать правильные параметры шага, взятия, рокировки. Мы вызываем методы много раз за ход при различных проверках, поэтому значения считанные из метода где происходит проверка например на шаг не верны.