Вперёд, к тёплому ламповому аналогу!

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

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

Количество параметров гугловской нейросети Inception третей версии — примерно 12 миллионов. То-есть, каждый раз мы считаем скалярное произведение матрицы с 12 миллионами элементов с точно такой же матрицей. Очень, очень вычислительно дорогое удовольствие.

Что с этим можно сделать? А, например, вот что. Можно каждый параметр представить резистором. Входное значение — поданное на него напряжение, вес — проводимость. Проводимость — величина, обратная сопротивлению: G = 1/R или же R = 1/G

А теперь закон Ома:

I = U/R, а R заменим 1/G: I = U/(1/G), упростим: I = UG. Подаём входное напряжение, и меряем ток. Вот вам и скалярное произведение, причём чисто аналоговыми методами.

Но хардверный резистор, разумеется, не очень удобно. Зато знаете, что удобно? Флеш-память! Флеш представляет собой миллиарды полевых транзисторов с изолированным затвором, ведущих себя как резисторы. Изначально на них хранили только 0 или 1, ток выше или ниже порогового значения считывался как ноль или единица. Потом сделали многоуровневую флеш-память, и на современных твёрдотельниках QLC каждая ячейка хранит аж 16 значений (4 бита). Теперь пошли дальше, и на этих электрически программируемых резисторах научились производить самые настоящие аналоговые вычисления, очень интересным применением которых и являются расчёты скалярных произведений для работы нейросетей.

Очень, очень интересные нынче вещи придумывают. Как вам такое — расчёты на жёстком диске?

Конечно, у подобного подхода есть недостатки: более низкая точность вычислений. Но нейросети, вообще-то и так работают по вероятностному принципу. Какая тебе, в сущности, разница, если нейросеть определяет фотки котиков с 99% точностью или “только” с 95%?

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

Игра для мальчишек и дяденек

С огромным удовольствием режусь со старшим сыном в прекрасную игру Scrap Mechanic. Это, как бы сказать, Майнкрафт с инженерным уклоном.

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

Смысл игры в том, чтобы выжить и не умереть с голоду. Точно так же, как и в Майнкрафте, нужно добывать себе еду. Съедобная фауна хоть и существует (и представлена симпатичными коровами), но непроста в приготовлении, поэтому лучше сконцентрироваться на выращивании овощей. В этом тоже есть свои сложности: если засеять сразу слишком большое поле, то набегут роботы и попытаются все посевы уничтожить — на этой планете выращивать еду разрешено только автоматам. Большие поля называются “нелегальными” и ночью к тебе приходит массовка роботов с целью разобраться, чьи в лесу шишки. И чем поле больше, и чем более ценные овощи там выращиваются (например, очень ценны брокколи), тем более крупная и опасная тусовка к тебе заявляется. Поэтому приходится выкручиваться: засевать много маленьких полей или же обильно удобрять поля с целью ускорить созревание овощей, чтобы успеть убрать урожай до прибытия аграрной полиции.

Но самый смак игры — в построении разного рода техники: автомобилей, грузовиков, тягачей, буровых установок, танков для борьбы с роботами, и так далее. Физика в игре сделана очень неплохо, и можно даже построить летающую технику. Но, опять же, из-за неплохой физики управлять ею крайне непросто. У меня ушёл битый час, чтобы сконструировать квадкоптер, на котором я бы не разбивался сразу же после взлёта. И ещё полчаса — чтобы научиться более-менее прилетать туда, куда надо мне, а не куда боги пришлют.

Есть самые разные строительные блоки, из которых можно собрать технику: двигатели бензиновые и электрические, подшипники, поршни, фары, таймеры, трубы самых разных длин и ориентаций, стекла, амортизаторы, шины, оптические сенсоры… Система крафтинга похожа на Майнкрафт: чтобы сделать тот же амортизатор, надо сначала добыть железо, которое можно либо набурить, либо переплавить незадачливого робота, предварительно огретого по кумполу кувалдой. Потом из железа надо сделать сталь, то-есть понадобится уголь. И нужна нефть для гидравлической жидкости. Нефть можно либо накачать в пустыне, либо достать со дна моря.

Но и это ещё не всё. В игре есть пара моментов, которые делают её интересной не только мальчишкам, но и дяденькам с высшим компьютерным образованием. Так, в игре есть логические элементы, что значит, что на их базе можно построить компьютер. Вот, например, я построил двоичный восьмибитный сумматор с последовательным переносом. Складываются числа 163 и 29 (10100011 и 00011101 соответственно). Результат, конечно, 192 (11000000).

Конечно, можно не только складывать, но и вычитать. Разумеется, компьютеры вычитать не умеют. Когда компьютеры вычитают, например, 29 из 163, они складывают 163 и -29. В двоичной системе, чтобы получить отрицательное число, надо все биты перевернуть и добавить единицу. Так что складываем 10100011 и 11100011 и получаем 10000110 (134). Ну, а грозно горящий красным индикатор переполнения игнорируем…

Элементы сумматора — пять логических элементов: два XOR, два AND и один OR. Проще не придумалось.

В-общем, в игре каждый может найти что-то своё, интересное лично ему. Кто-то любит драться с роботами. Кто-то строит огромные мощные седельные тягачи. Другой — автоматизирует выращивание овощей. Ну, а кто-то рисует логические цепи в творческом режиме — точно такой же режим есть в Майнкрафте. В нём нет врагов, и доступны все строительные блоки. Развлекайся как хочешь.

Крайне рекомендую, игра находится в активной разработке (т.н. early access), но уже стоит того, чтобы её купить. Есть на Стиме.

Что делать дураку

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

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

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

Натолкнулся на подобную задачку у avva. Берём четыре заданных числа. Можно переставлять их как хочется. Из инструментов — все четыре действия арифметики и скобки. Сумма должна получиться 24.

Простая задачка:

2,3,3,6

2 * 3 * 3 + 6 = 24

Сложная задачка:

1, 3, 4, 6

6 / (1 – 3/4) = 6/(1/4) = 6*4 = 24

Вы думаете, я руками решал? Да ну нахер такое, ненавижу.

Это менее 20 строчек на Питоне (на чём же ещё, если надо быстро):

from itertools import permutations

all_numbers = ['1','3','4','6']
all_actions = ['*','/','+','-']
all_parens = [['','','','','',''],['(','',')','','',''],['','(','','',')',''],['','','','(','',')'],['(','','','',')',''],['','(','','','',')'],['(','',')','(','',')']]

numbers = list(permutations(all_numbers))

for number in numbers:
	for i in range(0,len(all_actions)):
		for j in range(0,len(all_actions)):
			for k in range(0,len(all_actions)):
				for parens in all_parens:
					try:
						if (eval(parens[0] + number[0] + all_actions[i] + parens[1] + number[1] + parens[2] + all_actions[j] + parens[3] + number[2] + parens[4] + all_actions[k] + number[3] + parens[5]) == 24):
							print(parens[0] + number[0] + all_actions[i] + parens[1] + number[1] + parens[2] + all_actions[j] + parens[3] + number[2] + parens[4] + all_actions[k] + number[3] + parens[5])
							quit()	
					except ZeroDivisionError as e:
						print(e)

Не получилось только как-то алгоритмизировать создание скобок. Скобки, они, блин, хитрые. ()(), например, не палиндром. А ())( — палиндром. Поэтому в лоб написал все возможные варианты, благо, их немного.

Что делать дураку? Писать алгоритмы!!!

Аффтопрограммирование

В автомобили уже давно ставят компьютер с бортовой самодиагностикой. До 1996 года единообразия работы с этим компьютером не было, а теперь везде можно с ним поговорить по набору стандартов OBD2. Раньше сканеры, общающиеся с диагностической системой, были дико дорогими, но теперь цена стала более демократичной, и самые простенькие можно купить монет за 20, а то и ещё дешевле. Однако дешёвые сканеры имеют крайне ограниченные возможности, и способны только на самые примитивные действия — просмотр диагностических кодов (далеко не всех), их стирание. Если же тебе нужна диагностика чего-то более сложного, придётся серьёзно раскошелиться. Вот, например, возьмём такую распространённую вещь как диагностика катализатора. Когда у тебя вылазит код диагностики P0420, причины для него могут быть самые разные. Может быть, датчик кислорода подох. А может быть, и катализатор. Ведь как возникает этот код? У тебя стоят два датчика кислорода — один ДО, другой ПОСЛЕ катализатора (в машинах, которые дизайнили пидарасы в плохом смысле слова, их аж четыре — см. Ниссан). Код ошибки генерируется когда показания этих датчиков ОДИНАКОВЫЕ. Что логично — это означает, что катализатор ничего не делает.

Чтобы однозначно понять, надо ли менять катализатор, надо показания этих датчиков представить графически. Какие показания будут у них до того, как катализатор прогреется до рабочих температур. Какие после. Показания датчика ДО катализатора должны меняться, и довольно сильно. Показания датчика ПОСЛЕ катализатора должны оставаться постоянными. Увидев всё это, легко понять, что происходит. Но сканер OBD2, способный строить графики, уже недёшев — от 150 монет и выше.

Что можно сделать, если у тебя руки растут из (надеюсь) относительно правильных мест? Можно купить компьютерный адаптер на чипе ELM327, который подключается через USB и становится в компьютере дополнительным COM-портом. Они недорогие — за 10 монет можно купить. Затем берём любую терминалку, и цепляемся к этому порту, выставив скорости от 9600 до 38400 и 115200 (зависит от конкретного адаптера). И разговариваем с ним как с обыкновенным модемом. Ага. Он даже командой ATZ ресетится 🙂

Вот так, например:

OKL1 это на самом деле OK, выданное модемом на команду ATL1 (включающую добавление CR в ответы). Иначе человеку некомфортно.
AT@1 это запрос “ты кто такой”, типа ATI7 на модемах US Robotics 🙂

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

Судари мои, за что мы любим язык программирования Питон? Я вот раньше его недолюбливал, а потом оценил по достоинству. Язык Питон мы любим за то, что на нём можно решить практически любые прикладные задачи если использовать соответствущие библиотеки; ибо кто-то с такой проблемой уже, скорее всего, сталкивался.

Существует специальная библиотека Python-OBD, в которой вся эта расшифровка шестнадцатиричной бредятины уже написана, тебе остаётся только её взать и нарисовать, что тебе надо. В частности, оно может выдавать значения напряжения, выдаваемого датчиками кислорода. Остаётся сунуть эти значения в список (во что же ещё), после чего скормить его matplotlib.pyplot, и представить графически хоть чорта бритого, причём ровно так, как тебе надо.

Ну, а те, у кого с программированием не очень, могут приобрести коммерческие программы, работающие с адаптерами на ELM327. Их много всяких, и они недорогие — всяко дешевле 150 долларов.

Надо ещё сказать, что тут есть засада. Стандартные OBD2 коды хорошо документированы. Но есть и специальные, проприетарные коды, для каждой марки свои, и производители не спешат их описывать и выкладывать описание в открытый доступ. Надо же как-то заставить юзверей ушастых покупать обслуживание в дилершипах. Но есть недорогие программы, которые поддерживают и эти коды. Так, для БМВ есть Bimmerscan, а для Фордов есть Forscan, причём на него бесплатно дают пробную лицензию на два месяца. Кроме того, Forscan работает и не с Фордами, просто он не поддерживает специальные коды диагностики для автомобилей других производителей.

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

PS: Хех, вот уж не думал, что теги “автомобили” и “программирование” когда-нибудь встретятся.

Компьютерное

Проапгрейдил жёсткий диск в компьютере. Был 1 “терабайт”, стало 2. В кавычках потому что производители используют альтернативную математику — 1 терабайт у них это 1000 гигабайт, а не 1024.

Тупо перекинул всё Акронисом, благо с твёрдотела на твёрдотел всё копируется моментально. Лет 10 назад я бы всё переставил нахер с нуля, а щас настолько лениво всё это делать! Это что же, все программы с нуля переустанавливать, все игры, все настройки? Нафиг-нафиг.

А ещё я сделал одну вещь, которую тоже не стал бы делать 10 лет назад. Купил игровой ноутбук MSI. Это раньше я думал (ошибочно), что Компьютеры должны быть Большие и Железные, а теперь я ничего такого предосудительного в ноутбуках не вижу. Ноутбук не сильно выпендрёжный, но в нём стоит Нвидия 2060, ничуть не меньше по мощности, чем 1070 GTX, что стоит в стационарном компе. Игры идут замечательно. Да и всё остальное тоже.

Майкрософт, наконец-то, блин, решил давно существующую проблему: как получить компьютер, который может одновременно играть в игры, и работать с софтом под Линукс, которому нужна CUDA, и чтобы без установки двух ОС в многозагрузочной конфигурации. Я уже давно использую WSL (Windows Subsystem for Linux). Это позволяет постоянно иметь под рукой Линукс, на котором можно разрабатывать софт, не отходя от кассы. Не надо путать WSL с Cygwin — WSL это полноценный линукс, запускающий линуксовые же бинарники, а не перекомпилированный в экзешники линуксовый софт. Ещё в нём удобно обмениваться файлами с линуксовой подсистемой — ибо WSL создаёт скрытую шару \\wsl$, из которой ты имеешь возможность обращаться напрямую к / в линуксовой виртуалке.

Так вот, выяснилось, что начиная с WSL версии 2, ресурсы графического процессора нормально прокидываются к гостевой ОС, так что там можно запускать TensorFlow, Caffe, и прочие интересные вещи без того, чтобы тормозить и всё выполнять на центральном процессоре. Так что впервые, блин, можно и на ёлку залезть и не оцарапаться. Раньше подобные задачи решались установкой Линукса в качестве основной ОС, и водружением на него системы виртуализации Xen, которая запускала машину с Виндоуз, в которой уже можно было запускать игры, ибо Xen умеет пробрасывать GPU до гостевой ОС.

Конечно, есть небольшая потеря производительности и в том, и в другом случае. Но потеря производительности на 10% в играх — намного заметнее, чем потеря производительности на 10% при исполнении TensorFlow. Так что как ни крути, а всё же в этом отношении Виндоуз лучше Линукса.

Доломал минимакс

Вот многие считают, на мой взгляд, необоснованно, что машина, созданная человеком, завсегда будет дурнее создателя. По моему опыту, верно обратное — созданный человеком искуственный интеллект (оговорюсь сразу, для данной конкретной определённой задачи — т.н. “слабый” ИИ) работает намного мощнее, чем способен человек, его написавший. Во всяком случае, мои крестики-нолики легко меня громят, если только я не наморщу ум — тогда получается ничья. Да и Deep Blue, который обыграл Каспарова, писали хоть и люди, заведомо знакомые с шахматами, но всё же не игроки выше уровня великого шахматиста.

Поэтому, так сказать, в дальней перспективе я вижу, что человек сможет создать сильный искуственный интеллект, который превозойдёт его самого. Вопрос, какая роль будет отведена человеку в данном мире — ОЧЕНЬ интересный, и по-моему, однозначного ответа нет ни у кого. Элон Маск, например, считает, что человечество будет порабощено сильным ИИ. Создатели сериала “Person of Interest” думают, что человек будет существовать с сильным ИИ симбиотически — т.е. всё управление и развитие человечества возьмёт на себя ИИ, люди будут абсолютно счастливы, а в обмен на это будут этот самый ИИ обслуживать, например, батарейки вовремя менять 🙂 Ну, а создатели сериала “Westworld” отводят ИИ роль рабов, прислужников человека. Какой из этих ответов верный — неизвестно, но не исключено, что ответ мы узнаем в течение нашей жизни.

Однако хватит философии.

Вся задача написания игры, способной обыграть создателя, в итоге таки свелась к написанию алгоритма минимакс. В этом была вся загвоздка. Попытаюсь объяснить попроще, как он работает.

Для каждого потенциального хода нужно рассчитать некий коэффициент. Отрицательный коэффициент будет означать, что выиграл противник, положительный — что выиграла программа. Я начал с того, что присвоил немедленному выигрышу значение 1.0, проигрышу -1.0, а ничьей 0. Далее, алгоритм помечает этот ход как корневой узел, и строит исходящее из него дерево потенциальных ходов противника, а потом снова своих, вызывая сам себя рекурсивно (а как же ещё, если речь идёт о деревьях произвольной высоты). Раньше или позже, алгоритм доберётся до листьев игрового дерева, и будет возвращать +1.0, -1.0 или 0. Остаётся только сложить все значения, полученные из листьев игрового дерева, вместе, и записать их в массив, из которого выбрать максимальное значение, присвоенное какому-либо ходу.

Но этого оказалось недостаточно. Написанная с таким алгоритмом программа таки играла, но на среднем уровне. У неё можно было выиграть. Шишечкой на этой ёлочке оказалось введение дополнительной поправки, на которую умножался коэффициент, полученный из листьев игрового дерева. По простой причине — немедленный выигрыш или проигрыш, прямо со следующего хода, должен учитываться значительно больше, чем выигрыш или проигрыш после нескольких ходов. Я начал с того, что коэффициенты, полученные из каждого более нижнего уровня игрового дерева, стал делить на 2. Но и этого оказалось мало, хотя и заметно улучшило работу алгоритма. Магическим числом оказалось 4. Т.е. немедленный выигрыш на первом ходе учитывается как +1.0, выигрыш на втором — как +0.25, на третьем — +0.0625 и так далее. Вот тут уже выиграть против программы не оказалось никаких шансов. В лучшем случае я могу сыграть вничью.

Смеха ради, запустил программу играть против гугловских крестиков-ноликов на уровне сложности impossible. Все игры так же были сведены к ничьей. Урррря!!

Надо будет написать программу, играющую в преферанс. А то комп меня легко дрючит, особенно на распасах (я вообще не очень играю ни в преферанс, ни в шахматы, ни в шашки, хотя почему-то неплохо — в поддавки).

IT-гримасы кризиса

Все помнят Y2K? Тогда огромное количество существующих государственных систем потребовали переписывания, так как они некорректно отрабатывали двузначные даты. Огромное количество этих приложений были созданы в 1970-80е на Коболе, и внезапно программисты на Коболе оказались дико востребованными.

Теперь в связи с вирусным кризисом мы оказались в той же ситуации — эти государственные компьютерные системы никуда не делись, но из-за огромного наплыва тех же безработных, подающих на пособия, они не справляются с нагрузкой. Штат Нью-Джерси ищет программистов с опытом программирования на Коболе, починить их древнюю систему обработки заявлений на получение пособий.

Правда, ищут они волонтёров, то-есть, предлагают работать за бесплатно, так что #goodluckwiththat

И не вполне понятно, чего они хотят починить. Древний мейнфрейм, хоть ты программу обпереписывайся, быстрее работать не станет.

Поглядел я этот Кобол, кстати. Дико раздражает его многословность. Даже в таких простых вещах как операторы сравнивания. Чего стоит, например, условие “A не равняется B”. На Сях оно просто: A != B. А на Коболе надо писать A IS NOT = B. Ага, вот так, знай наших! Мы не как другие всякие! Меня, кстати, то же самое раздражает в Повершелле. Там нельзя написать A > B. Надо писать A -gt B. Дичь какая-то. Создателем Кобола, кстати, является женщина, и я не хочу показаться сексистом — но может быть эта многословность оттуда?

Про 42

Хотел написать про то, как мне лично было непонятно, чем так гордится группа исследователей Массачуссетского Технологического, которая нашла значения x, y, и z, при которых x3 + y3 + z3 = 42.

Набросал для расчётов свою прогу на Джаве. И не могу сказать, что она не работала. Она прекрасно работала для многих цифр, в том числе, и для любимого числа Шелдона Купера (73). Но дальше, имея на руках порядки полученных в MIT цифр для 42, прикинул вычислительную сложность, и охренел — т.к. решать данную проблему, как говорится, “в лоб” на самом ультрасовременном суперкомпьютере с его двумя сотнями петафлопсов с лихером придётся э…. не намного меньше, чем возраст наблюдаемой Вселенной.

Устыдился, пошёл читать про алгоритм, которым раньше было решено уравнение x3 + y3 + z3 = 33. Оказалось, что там, мягко говоря, очень не в лоб решали. Устыдился окончательно. Полезно вот так иногда, рожей об стол, для скромности и смиренности.

Вопросы на интервью, помощь зала

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

Сижу чешу репу над списком вопросов.

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

1. Если нужно совершить одно и то же действие пять раз, как это лучше всего сделать внутри скрипта?
2. Если мне надо получить пронумерованный список всех компьютеров в домене, как проще всего это сделать?
3. Нужно написать скрипт, который будет посылать извещение сисадмину, если в домене появятся учётные записи, пароль которых никогда не истекает. Как это лучше всего написать?
4. if (a = 0) { .. } — почему данное условие либо не работает вообще, либо не работает правильно?

Какие ещё будут предложения?

Компьютер всё делает лучше

Нашёл тут задачку судоку, типа, самая сложная в мире.

https://gizmodo.com/can-you-solve-the-10-hardest-logic-puzzles-ever-created-1064112665

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

Скорее всего, “сложной” она является только потому, что решить её логически очень сложно, а вот перебором — пожалуйста. Удивительно только что самые разнообразные задачки судоку моя программа решает в среднем за 2 секунды, а тут получилось значительно быстрее. Видимо, то, что заточено под логику, сложнее для компьютера, и наоборот, то, что человеческий мозг ставит раком, для компьютера ерунда.