Итак, вот черновик (ещё пару раз перечитаю и обдумаю) начала новой темы, прошу покритиковать (кроме размера, сам знаю, но короче не получается):
Для кого и о чём эта тема.Народ выразил желание изучить ассемблер для написания быстрых программ для решения
вычислительных задач, причём фактически с нуля. И если книг и (видео)лекций по ассемблеру достаточно, то по оптимизации программ по скорости их гораздо меньше (и многие сильно устарели), а уж про использование для этого технологий векторных вычислений (MMX, SSE, AVX) совсем мало. Во всяком случае на русском.
Основная цель использования ассемблера в данной теме - максимальное повышение скорости счёта. Достаточно узкий класс задач. И речь не про задачи на пару минут или пару часов, а на пару недель или месяцев (а то и лет).
Соответственно все прочие вопросы, как то: ввод/вывод данных (за исключением ввода параметров счёта и вывода результатов), любая графика и звук, веб сайты и любые сетевые технологии (возможно за одним исключением), игры, и многое другое - рассматриваться не будут. Для всего этого есть более удобные языки программирования. К которым можно будет или подключить кусочек на ассемблере ради ускорения нескольких функций, или воспользоваться встроенным ассемблером для тех же нескольких функций.
Когда и как и в каком объёме затрагивать вычисления с плавающей точкой - пока не знаю, это достаточно отдельная большая тема, посмотрим по ходу дела будет ли интерес, насколько я понимаю пока народ интересует ускорение целочисленных вычислений.
Ограничения.В качестве компилятора ассемблера буду использовать FASM как достаточно современный и бесплатный и компактный и просто мне нравится больше остальных.
Писать будем исключительно под винду, в общем любую, но не старше WinXP (запустится ли под Win2000 вопрос, по идее должно). И не новее Win7 - даже под Win10 всё работать тоже по идее должно, но проверить мне сложно, а про Win11 и новее даже думать не хочу (но опять же, по идее работать должно). Но это и непринципиально так как от ОС зависят лишь служебные куски кода, а вычислительная часть от ОС обычно практически не зависит (обрабатывать терабайты или использовать сеть в любом виде не планирую, это задача более высокого уровня на нормальном языке).
Любые другие ОС в пролёте, и MacOS, и все (под)виды Linux, и Android, и что там ещё в мире существует. Я их просто не знаю в достаточной мере.
В основном все примеры будут под x86 (32-разрядные) так как это более совместимо.
Для иллюстраций буду использовать код на PARI/GP (простой язык, довольно похожий на С, удобный быстро что-то посчитать, плюс для работы нужен всего один файл .exe, плюс его многие здесь уже неплохо знают) и на C (его любой программист должен уметь как минимум читать/понимать) если будет необходимость.
Предполагается что с работой в винде - создать файл с нужным именем
и расширением, создать папку, сложить файлы в нужную папку, что такое консоль и права доступа, как запустить файл .exe и мышкой в проводнике и клавиатурой в консоли - человек уже знаком. И отвечать на бесконечные вопросы типа "а куда я сохранил текстовый файл? и как мне его теперь найти?", "а почему .doc или .docx не хотят работать если сказано сохранить в .txt?" и аналогичные не буду, тема про ассемблер, а не работу в винде.
Также предполагаю что человек знает (или сам прочитает) про арифметические операции, про виды кодирования чисел (во введении расскажу про какие надо и где найти), про логические операции и чем они отличаются от арифметических (тоже видимо поясню, но совсем коротко), про основные алгоритмические конструкции (линейный код, условное выполнение, циклы, процедуры, отличие от функций в математике, это всё тоже коротко опишу во введении). Простите но пересказ всего курса информатики я не осилю, и не в этой теме.
WinAPI будет использоваться (по необходимости), но чисто как "заклинания" для того-то и того-то, без подробных разъяснений. Не потяну. Это отдельная огромная тема, много где уже освещена. Да и онлайн справка есть (на английском на сайте MS). Приведу примеры как использовать нужное конкретно под FASM и на этом всё.
MMX упомяну, но описывать и рассматривать не буду, оно устарело.
AVX-512 тоже рассматривать не буду: мне не на чем проверять. И подозреваю заинтересованным товарищам тоже. Да и там по сравнению с AVX/AVX2 сильно изменилась идеология, это может дать дополнительный выигрыш скорости (кроме вдвое шире регистров), но требует и переосмысление кода, и алгоритма, и даже полной смены алгоритмов вычислений. Короче без проверки это утопия. Очень интересная технически, но всё же утопия.
Рассказывать ли про длинную арифметику в общем виде ... Думаю нет. Только коротко несколько практически полезных (в интересных мне и кое-кому ещё) частных случаев. И только ради новых команд процессора и иллюстрации сколько при этом подводных камней.
Темы многозадачности, обработки ошибок (за малым исключением), стресс-тестов и вообще тестирования программ (не специфичные для ассемблера), вообще техники написания (доказуемо) надёжных программ - всё мимо. Это общая информация без привязки к языку программирования. Да моих знаний может оказаться маловато.
Рассказ об отладчиках (а все книги говорят что без него никуда) пока под вопросом, это отдельная программа, встроенный в винду (кстати не факт что есть и в новых) убогий, тот чем пользуюсь сам замороченный. Если включу, то видимо после второго пункта (см. ниже план) отдельным отступлением. А может ограничусь показом как выводить много самой разной статистики и потом анализировать что же там в вашей программе происходит на самом деле.
План мероприятия.В следующем сообщении предполагаю дать коротко основные базовые сведения для начала работы: что внутри процессоров с точки зрения программиста, как они работают и как ими управлять, зачем нужен язык ассемблера, где взять его компилятор, что он (и процессор и компилятор ассемблера) умеет и главное что он не умеет, как настроить компиляцию своих будущих программ на асме, где смотреть справочную информацию (например список команд процессора), поток выполнения и его изменение, может ещё что-то что вспомню по ходу дела.
В третьем сообщении собственно приступим. После каждого пункта пауза на вопросы и ответы.
1. Разумеется сразу в бой - покажу тестовую программу (вычисление 45-го числа Фибоначчи) и подробно расскажу что, как, зачем и почему она считает. И как вообще записываются команды и прочее.
Либо сразу же, либо в следующем сообщении разберу понятие символического имени для констант и переменных и видимо и варианты их хранения в памяти.
Где-то тут, или по ходу дела, или отдельным сообщением, попробую разобрать возможные ошибки и к чему они приводят.
2. Дальше изменим программу чтобы она считала любое число Фибоначчи до 48-го, причём указываемого в параметрах при запуске. Это добавит две большие (раз в 5 больше всей предыдущей программы) процедуры с кучей новых команд, вот и будем их разбирать, заодно и как процедурами пользоваться. И включаемыми файлами (.inc) чтобы не захламлять код в основном файле.
3. Далее нужно будет сказать об отличиях x64 от x86 и переписать программу под x64 чтобы можно было вычислить числа Фибоначчи до 93-го. Возможно чуть перепишу одну из больших процедур чтобы показать новые команды процессора (более удобные программисту).
4. Если будет запрос на вычисления с плавающей точкой, то тут удобно сделать отступление и переписать программу для вычисления любого числа Фибоначчи по формуле Бине с точностью 17-18 старших цифр. Потребуется дополнение внутреннего устройства процессора (FPU) и новые команды.
5. Дальше удобно рассказать об MMX (чисто в историческом плане), SSE и AVX и переписать программу на SSE и AVX для вычисления одновременно сразу двух и четырёх чисел Фибоначчи. Либо методом суммирования целых (до 93-го даже под x86), либо ещё и по формуле Бине если было про FPU. Куча новых команд ...
Думаю всё выше займёт недели две. И мне надо всё сформулировать и написать, и код написать и проверить, и на вопросы ответить ... Не, думаю быстрее не выйдет. Только если вдруг все желающие всё это уже и так знают.
Здесь сделаю паузу чтобы ответить на вопросы, потренировать в исправлениях программ под разные варианты задачи (что-нибудь непременно придумаю) в виде "домашнего задания", если хорошо пойдёт, то и написать самим что-то простенькое (пока не знаю что, посмотрим). Просто для наработки практики и снижения страха перед великим и ужасным ассемблером.
Займёт это сколько займёт, пока интерес не угаснет или желание идти дальше не пересилит.
Пора приступить к чему-то полезному. Знаю что одной из целью было поиск цепочек простых чисел, вот и займёмся проверкой чисел на простоту. Решето Эратосфена пропустим, оно интересно лишь парой новых команд, а оптимизировать его на данном этапе слишком сложно и непрактично. А кому "очень надо" - есть прекрасные готовые программы в исходных кодах, можно изучать. Быстрее них я сделать не умею (точнее мне терпения не хватает, слишком много надо придумать и реализовать).
6. Проверка числа на простоту. Сначала тупо проверкой делимости. Потом тут же сразу и красивый метод замены медленного деления на быстрое умножение. Понятие о времени выполнения команд (и где смотреть инфу). Разные процессоры и разная скорость одних и тех же команд. И соответственно необходимость разных вариантов кода для разных процессоров. Понятие псевдопростого числа. Тест Ферма и быстрый его вариант. Комбинация разных методов. Варианты под x64 метода с умножениями и теста Ферма. Замеры скорости всех вариантов и сравнение. Как вообще более-менее правильно мерить скорость своих программ.
Очень большой пункт. Наверное на неделю с лишним только рассказа, плюс вопросы и обсуждение ... Зато будет задел для следующих практически полезных пунктов, к чему собственно и хотелось дойти.
7. Поиск цепочек простых чисел. По паттерну (и кратко что это вообще такое). Модулярная арифметика (коротко и только нужное). Сначала поиск с делениями. Потом с умножениями вместо них. Потом с суммированием. Потом векторизация (SSE и AVX). По ходу изложения разные трюки для ускорения, не всегда из книг. Разные варианты кода одного и того же алгоритма и сравнение их скорости.
Тоже очень немаленький пункт. Где-то тут может быть скорость наших программ превысит скорость среднего С кода ... А может и нет, но хотя бы подберётся.
8. Отступление в сторону для практической пользы. Разделение работы между разными программами и языками (использование связки aасм + PARI/GP). Понятие фильтрации кандидатов в решения и выбор глубины (качества, отношения) фильтрации. Примеры деления работы между асмом и PARI и сравнение скорости. Получение .dll вместо .exe для использования в других языках (практически всех, кроме PARI/GP).
9. Если хватит сил, то примеры тонкой оптимизации по скорости для конкретного процессора. И в теории, и на практике (которая тут часто противоречит теории). Наверное здесь и новые возможности FASM введу для сокращения кода и повышения его понятности.
Вероятно тут (почти) доберёмся до реального кода моей программы и достигнем понимания как же он чёрт возьми работает. И хоть занимает буквально 3-4 десятка строк, но для понимания нужно почти все что выше.
Собственно на этом основная цель достигнута.Займёт это пару-тройку месяцев. Плюс-минус. Впрочем, как известно, любые сроки называемые программистами надо умножать на 3, а для больших проектов (больше недели/месяца) и на 5.
Ну, тут больше будет зависеть от собеседников, насколько придётся углубляться в детали или уходить в сторону при ответах.
Дальше в режиме свободного полёта, по вопросам и заявкам
трудящихся собеседников, что интересно им.
Как можно заметить совершенно не затронута тема многозадачности/многопоточности. Да. Я её реализую или на другом языке, или на уровне WinAPI, это уже не ассемблер. Спускать её на уровень ассемблера ... извините глупость (или чисто ради развлечения). Мне не хватит ни сил, не желания, ни знаний. Другая не менее важная причина: многозадачность сильно неинтуитивна и требует заметно других навыков написания кода чем были наработаны выше. Да, вот такая засада! Совсем не зря многопоточность (и тем более многозадачность) считается одной из самых трудных для новичков и достойна не меньшей темы. А если на неё наложить ещё и трудности ассемблера ... Не, это без меня. Ну или не здесь.
PS. Может показаться что цель похвалиться своим кодом. Ну, да.
На самом деле это просто хороший пример (многолетней!) глубокой оптимизации ассемблерного кода по скорости выполнения. С использованием самых современных возможностей (доступных мне SSE и AVX2). Часть примеров на самом деле не используется (тест Ферма), зато на них удобно показать другие команды процессора и оно полезно практически.
План не окончательный, приветствуются предложения и поправки. Как по сокращению, так и по расширению и углублению.
Вопрос с литературой для отсылок за подробностями пока прорабатывается, что-то очевидно будет, но может на каждый конкретный вопрос хватит и вики.
Где придётся упомянуть наличие и размеры кэшей в процессоре и оптимизацию под них - не знаю, как пойдёт, где понадобится, там и будет. Вообще собираюсь рассказывать про процессор (а без этого никуда) постепенно, только нужные на каждом этапе вещи. И половина (или больше) внутреннего устройства процессора останется вообще за кадром - в данном классе задач оно программисту не нужно, на скорость счёта не влияет.
Пишется это всё для тех 5-ти человек что выбрали второй вариант ответа в опросе (поспрашиваю). Отдельно буду благодарен выбравшему третий вариант (поотвечаю). Выбравшие первый вариант (почитаю) вряд ли найдут для себя что-то новое и
, я собираюсь превратить это не в лекцию, а наверное в семинар (рассказ кусочка с примерами и вопросы/обсуждение по нему). Впрочем надеюсь и эти 10 человек примут участие содержательными вопросами или ответами в процессе обсуждения. Двери открыты.
А пока жду критики и пожеланий по существу.