Chat:Ru/2020-06-13
ilt: amurushkin это легко проверить
ilt: я контрольную функцию написал
ilt: она перед таким таймаутом должна вывести сообщение
ilt: переписал, прикол в том что даже локально теперь стали сыпаться таймауты
BorisZ: ilt можно попробовать в начале каждого хода запускать сборщик, тогда хотя бы твой контроль времени будет отрабатывать
BorisZ: я не уверен правда что в джаве можно его прям запустить насильно, но какие-то средства должны быть
ilt: нельзя его принудительно запустить
ilt: можно попросить "запусти пожалуйста"
ilt: уже проверил это тупиковый вариант
BorisZ: смутно помню давно читал статью что можно свой сборщик прикручивать вместо стандартного
BorisZ: вроде на хабре была статья, но это давно и не точно
BorisZ: ну и не факт что тут получится
BorisZ: там как раз был пример что прикручивали сборщик который ничего не собирает, просто падает когда всю память выели
BorisZ: и там получалось время выполнения предсказуемое
ilt: я пошел путем как amurushkin и YurkovAS посоветовали
ilt: сейчас еще прикручу локальной прогон реплея из json файла
ilt: и буду дебажить
amurushkin: я у себя правильность роллаутов проверял тем что выводил доску на каждом ходу и смотрел как он играет :) правда так совсем явные косяки только можно найти наверное. заморишься смотреть :)
ilt: я также проверяю
vrabosh: какой размер текста можно в редактор загружать?
tomatoes: 100kb
vrabosh: http://chat.codingame.com/pastebin/abc091f4-c80e-47a1-9ba4-4e6a8a84666c
vrabosh: смотрите прикол... допустим ствлю 20 время отккика 20-50 может быть
vrabosh: ставлю range(50) ну или другое чуть больше число, и отклик может быть за 1500
vrabosh: как так?
vrabosh: вот сейчас поставил 40, отклик 61, поставил 45, отклик уже 2300
vrabosh: хотя таймаут не дал
amurushkin: сначала надо инпуты считать
vrabosh: так это я вверху делаю. просто скорость хотел проверить как цикл гоняется
tomatoes: если иногда скачет, то наверное просто еще чтото жрет процессор
vrabosh: я так посмотрел, теоретически если некоторые данные загнать в массив, то можно до 200к цикл прогнать на поверки..
vrabosh: в минимаксе по 100к на каждого игрока, это норм?
tomatoes: ничего не понял
Uljahn: vrabosh: убери round и int
BorisZ: vrabosh а что ты пытаешься измерить то в своем примере?
BorisZ: память то выделяется в первой строке, которая не меряется у тебя никак получается
BorisZ: там может 1мс пройти а может 100 если сборщик запустится
BorisZ: внутри цикла ты как раз ничего не выделяешь
Uljahn: for j in range(50):
a = 19999 if any(i for i in gfull) else 29999
Uljahn: так разброс поменьше при замерах
Uljahn: чё-то фигню написал, надо же ещё проверку одну добавить, и кофе выпить
Uljahn: или заменить всё одной проверкой последнего элемента :confused:
Uljahn: а то мы тут предсказатель ветвлений замеряем
BorisZ: вряд ли в питоне как-то задействуется предсказатель этот
BorisZ: хотя фиг знает
BorisZ: транслятор же
Uljahn: короче, да, пример ни о чём
BorisZ: гиблое это дело - крестики на питоне
BorisZ: демотивирующее
BorisZ: бросай, Uljahn
BorisZ: завезут JIT - оно и так взлетит
BorisZ: пока не завезли, все впустую
BorisZ: может не взлетит конечно, но будет смысл побороться
BorisZ: сборщик мусора никуда не денется
BorisZ: будет борьба с таймаутами как в джаве
Uljahn: import gc; gc.disable()
Uljahn: частично отключает сборку
Uljahn: ну и если в нумпи всё делать, то и сборки не будет
Uljahn: нашёл всего один таймаут у себя, и то - когда противник даёт фримув :relieved:
Uljahn: можно начать с малого - топ-100 в голде, там ни одного питона
BorisZ: смотря как быстро дерево будет расти
BorisZ: если как у топов, то придется переиспользовать память, не хватит
BorisZ: у меня с 20к ролаутов хватает вроде
Uljahn: 20M нод не хватит?
Uljahn: ну, тогда придётся рут в начало смещать
Uljahn: даже 23М получается выделить, это при том, что ноды можно немного ужать и отключить выравнивание
tomatoes: у меня 4м хватает если в 95мс укладываться. и это при том что родитель и дети могут далеко друг от друга лежать
tomatoes: и 20м за лимит памяти вылезет наверное
tomatoes: в 38 байт хз как ужать :rolling_eyes:
Uljahn: по 4 байта на скор и визиты, один-два байта на индекс хода, 4 байта - индекс первого чайлда, один байт - количество чайлдов, итого 14-15, что я не учёл? :confused:
Uljahn: парентов не храним, отдельным списком при селекшне трекаем для бэкпропа
gybson_samara: 4 байта это 32 бита же, огромное число
vrabosh: как питон без руб прав может положить систему? под линуксом?
vrabosh: причем такоеже и в винде было...
tomatoes: игру ходить при выборке?
Uljahn: а чё было в винде? синий экран?
vrabosh: просто зависает.. и даже клава не работает
Uljahn: точно питон виноват? температуру проца помониторь
vrabosh: я создал массив на 100мбайт, и случайно его запустил вот так aa(fun()) и звисло
vrabosh: а понял, может быть. нагрелся от этого
735487: я тут как то на плюсах память выделял :) 16 гиг быстро кончилось ))
tutubalin: amurushkin а ты логарифм по таблице считаешь?
735487: логарифм кеширую если ты про это
tutubalin: я тут подумал: натуральный логарифм можно заменить на двоичный
tutubalin: а двоичный (не особо точно) можно считать гораздо быстрее
tutubalin: Инструкция LZCNT - Leading zero count.
tutubalin: (32 - LZCNT) примерно равно двоичному логарифму
tutubalin: точнее (31 - LZCNT)
YurkovAS: tutubalin или воспользоваться быстрыми функциями от смитса, он как-то выкладывать в общем чате. там логарифм, корень, обратный корень и рандом без остатка от деления :smiley:
tutubalin: ну рандом без остатка от деления - это вообще правило хорошего тона. так всегда надо поступать
ilt: YurkovAS а у тебя нет кэширования?
YurkovAS: все кешируется
tutubalin: очень многие популярные ГСЧ страдают тем, что младшие биты у них не такие уж и рандомные. если делать через остаток от деления, то могут быть нехорошие корреляции, например, когда делаешь RND%4 или RND%8
ilt: я в этой формуле имею ввиду
YurkovAS: да, в формуле все закешено
YurkovAS: смитс "в обсуждении топов" сказал, что его бот без книги будет на 2-м месте. круто
tutubalin: а как смитс корень быстрее FPU считает?
735487: самое интересное что у него он и с книгой на 2 месте ))
vrabosh: x,g = '2;12S;6R;18S'.split(';',1) g = (j for j in .join([i[-1]*int(i[:-1]) for i in g.split(';')]))
vrabosh: можно как нить это покрасивей написаь, но также в 2 строчки)
vrabosh: надо чтоб был генератор g = ('S','S'..12раз...'R'.. итд)
735487: s 12 раз это 'S'*12
735487: зачем так сложно то? куча разделить - соединить
BorisZ: покрасивей - шрифт поменять на готический )
BorisZ: либо красиво либо в две строчки
BorisZ: x, g = "2;12S;6R;18S".split(";", 1) result_str = "".join(p[-1] * int(p[:-1]) for p in g.split(";"))
BorisZ: вобще весь этот годгольф сомнительный навык какой-то, для людей же пишутся программы, а не для компов
BorisZ: а если человек для которого ты это написал окажется впыльчивый боксер
BorisZ: и с плохим зрением, у которого от скобочек в глазах рябит
tutubalin: vrabosh "S"*12 + "R"*6+"S"*18
vrabosh: tutubalin , посмотри скрипт..
vrabosh: там первое делает как раз [s*12],[r*6] потом это в одномерный массив.
tutubalin: а, ну тогда хз как это красивее сделать. и так красиво вроде
BorisZ: у меня красивее жеж - нет вложенных for
BorisZ: а строка от генератора ничем не отличается с точки зрения использования, еще и удобнее
Uljahn: x, g - за такие имена по рукам надо :)
BorisZ: это видимо из клеша какого-то задачка
BorisZ: тогда в одну строчку можно
tutubalin: может x - это координата, а g - ускорение свободного падения
ilt: если я ставлю HEAP_SIZE = 2 000 000, то секунду только создаю эти все ноды
BorisZ: если нода состоит только из интов, то можно выделять массив из интов
BorisZ: в конструктор ноды передавать индекс следующей свободной ячейки
ilt: нет не только из интов
ilt: пока хватает миллиона
ilt: а если у меня что-то написано типа Node node = nodesHeap[rootIndex]
ilt: от этого тоже надо отказаться?
ilt: эта нода условные три раза обрабатывается
BorisZ: я просто вслух думаю)
vrabosh: у меня переменые длинее 5 символов не бывают)
Uljahn: ilt: а клонировать не пробовал?
BorisZ: вместо класса Node сделать класс, у которого под капотом будет большой массив интов
BorisZ: он будет менеджером памяти как бы
BorisZ: тогда нода будет индекс в этом массиве
BorisZ: а у менеджера будут методы типа getVisits(int node) и так далее
ilt: пробовал тоже время
Uljahn: при создании объектов оверхед конечно выше, чем если просто под массив интов память выделять
Uljahn: а нужны там объекты? может, 2D массивом можно обойтись?
BorisZ: да, странно массив примитивов должен моментально выделяться вроде
gybson_samara: Uljahn +1, поэтому сипипи и выигрывает
gybson_samara: я в пакманах столкнулся с необъяснимым увеличением времени выполнения в нампи с указанием типа, дефолтный риал в разы быстрее оказался
gybson_samara: риал, флоат, не суть =)
Uljahn: gybson_samara: даже в numpy быстро получается, 20 миллионов нод за полсекунды, правда ноды типа struct
Uljahn: а какой указывал?
gybson_samara: Uljahn in8
Uljahn: float16 не родной для numpy, он эмулируется)
Uljahn: int8 должен быстро работать
gybson_samara: ну реально, указал инт и сразу таймаут жесткий
gybson_samara: убрал и в голде
gybson_samara: ну т.е. в серебре, потом до голды допилил
gybson_samara: могу скинуть код, добавишь в создание массива тип и проверишь
Uljahn: давай
gybson_samara: http://chat.codingame.com/pastebin/4130d105-3aac-46c7-a023-0fe4a5ed3873
gybson_samara: не лезет
Uljahn: ой-ой
Uljahn: а только массив если? мне весь бот не нужен)
gybson_samara: self.cross = np.zeros((height,width))
self.crossvisit = np.zeros((height,width), np.intc) self.simfield = np.zeros((height,width)) self.blocked = np.zeros((height,width))
gybson_samara: щас всем полставлю intc, кстати
gybson_samara: сразу таймаут
gybson_samara: ааа, тут ошибко\
gybson_samara: гребанный гит
gybson_samara: табы похерил
Uljahn: int8 реально тормозит
gybson_samara: ну вот
Uljahn: примерно в 10 раз медленнее при инициализации массива нулей
gybson_samara: я о чем и говорил
gybson_samara: и как я это должен предвидеть?
Uljahn: так это zeros, а попробуй ones))
Uljahn: там всё наоборот
gybson_samara: Uljahn это надо весь код наоборот переписать
Uljahn: я про то, что zeros - это хитрый зверь
Uljahn: нужно сравнивать с np.empty, который только память выделяет
gybson_samara: такс
gybson_samara: а эмпти это не 0?
Uljahn: нет
Uljahn: ничего не обнуляет, просто резервирует область памяти
gybson_samara: логично, но мне надо арифметическую матрицу, без симулякров
Uljahn: ты её потом будешь заполнять же?
Uljahn: или тебе нужна именно матрица нулей?
gybson_samara: потом буду заполнять значениями не ноль
gybson_samara: разумеется мне не нужна мтарица со случайными значениями
BorisZ: вы проверьте время, скорее всего zeros будет совсем ненамного больше чем empty
gybson_samara: Uljahn нампи без указания типа работает быстрее, факт. И это нельзя объяснить тем, что "флоат" ноль быстрее "инт" ноль и точка
BorisZ: там разница в одном вызове memset который должен быть очень быстрый
gybson_samara: Нампи с указанием типа тормозит
Uljahn: ну, потому что нампи оптимизирован под значения типа по умолчанию
Uljahn: кстати, посмотрел, empty нули выделяет
gybson_samara: Uljahn я не против, просто надо учесть
Uljahn: но это вроде не гарантируется
gybson_samara: Uljahn получается питон несколько унижают
gybson_samara: намеренно или нет
Uljahn: в смысле?
ilt: хорошо пошло
Uljahn: угу, что пофиксил?
ilt: я все переписал можно сказать
ilt: на 100 игр 2 таймаута
ilt: во второй части было похуже с таймаутами
ilt: но терпимо
ilt: amurushkin ты здесь?
735487: да
ilt: скажи, а если у меня что-то написано типа Node node = nodesHeap[rootIndex]
ilt: от этого тоже нужно отказаться?
735487: если копирование происходит то да желательно
ilt: node там несколько раз дальше используется
ilt: каждый раз писать nodesHeap[rootIndex]?
YurkovAS: там указатель, 99%, так что без разницы.
YurkovAS: ты же заполняешь в каждую ячейку nodes[0] = new Node(); nodes[1] = new Nodes();
ilt: да
YurkovAS: значит в массиве лежат указатели (адреса) Node node = nodes[1]; не копирует, а node это указатель и содержит адрес. но, это 99%, может ошибаюсь.
YurkovAS: amurushkin правильно?
YurkovAS: http://chat.codingame.com/pastebin/f34b064f-01c6-4158-af9b-38974343d160
ilt: да изменится
YurkovAS: а если бы копировалось, то изменялась бы только копия. в яве все классы указатели.
ilt: часть таймаутов точно имеет баговую причину
ilt: буду искать
MAKMED1337: я могу как-то посмотреть условие что будут в следующих лигах ?
Uljahn: в некоторых мульти полные правила на гитхабе вылодены, а так - нет, но мы можем подсказать
Uljahn: *выложены
ilt: скорость создания объектов это глобальный фейл
ilt: а в плюсах с какой скоростью они создаются?
YurkovAS: не замерял, но очень быстро и на 1-м ходу есть еще 900мс
YurkovAS: хотя, точно не скажу, это у меня тайминг такой.
ilt: а можешь тест сделать?
ilt: там 5 строк
YurkovAS: http://chat.codingame.com/pastebin/ba0daa03-036c-462b-bb99-a088e61842c0
ilt: у меня 400 мс 1 000 000 объектов создается
ilt: печалька
ilt: можно что-то делать до первого ввода и это не входит в время первого хода???
735487: ilt: скорость создания объектов это глобальный фейл, все зависит от конструктора. и на плюсах ловил я таймауты с конструктором
YurkovAS: в общем работает и так Node *nodes = new Node[15mln]; занимает 0мс - без констрактора занимает 2300мс - с конструктором типа: score = 0;
ilt: их ты потом все равно создаешь?
ilt: Смысл иметь массив без объектов
YurkovAS: память выделена, просто там мусор. поэтому потом уже, когда заполняешь данными, то всем полям указываешь значения
ilt: строка nodesHeap = new Node[HEAP_SIZE]; тоже быстро выполняется
YurkovAS: в твоем случае это массив указателей. т.е каждая ячейка занимает адрес (8байт)
ilt: перенос создания объектов во второй и следующие ходы сильно уменьшает количество роллаутов
YurkovAS: до первого импута у меня работает 2-3 сек. можно на это завязаться. потом читаешь импут. и еще 800мс дальше создаешь ноды + 100мс на мктс
ilt: вообще я затупил у меня отсчет начинается после первого ввода тоже
ilt: и я могу спокойно 2 секунды создавать 5м объектов
Uljahn: а на питоне не выделяют дополнительное время, потому что нет компиляции :(
Uljahn: хм, если от самого запуска замерять, то тоже 2.5 секунды получается :upside_down:
Uljahn: вот значит как надо было, теперь у меня тоже под 30кк нод выделяется за 3 секунды и 600МБ
Uljahn: с выравниванием накосячил - 480МБ, можно ещё значит
Uljahn: не понимаю, где косяк - выделяется 100М нод и память не кончается :joy:
Uljahn: нумпай в дебаг пишет - число нод: 1090000000, занято памяти: 17440000000 надо спать идти, Automaton2000
Automaton2000: если у меня массив предварительно созданных нод то по логике ведь объекты в нем живут пока идет игра