Zealint писал(а):
Первое. У нас есть набор функций, некоторые из которых могут быть параллельными. Однако в ряде случаев встраивание параллельных команд может замедлить функцию в последовательном исполнении на одном ядре. Это не часто случается, но случается. Поэтому с моей точки зрения нужно либо иметь по две версии каждой такой функции,
Я думаю,
первое и
второе наблюдения противоречат друг другу. Если делать разные версии библиотек на каждый чих, то сразу же получим раздувание кода в два раза, новые проблемы в виде выбора, с какими библиотеками линковать, и погоню за
избыточной универсальностью. А впоследствии этот шлам будет тянуть вниз ещё и грузом совместимости. Т.к. "это не часто случается" а одноядерные процессоры исчезают даже в планшетах, предлагаю расслабиться и смириться с вероятным падением производительности на одном ядре. Тем более, по той причине, что когда производительность критична, мы как раз стараемся использовать параллелизм.
Zealint писал(а):
либо в языке должна быть предусмотрена возможность перекомпиляции кода с игнорированием команд параллельной обработки. В последнем случае мы не всегда будем получать корректный код.
Есть ли пример, когда последовательное выполнение
корректного параллельного исходного кода изменит семантику?
Zealint писал(а):
Есть дофига всякокой фигни, и когда программист пишет template <class T, class U, class V, … > graph : public fuckingGraph { std::link <U> edges … } - он уже фактически начинает копать могилу своему творчеству. Так делает, например, Р. Седжвик.
Седжвик решает совсем другие задачи. В двух учебных курсах алгоритмов на Курсере Седжвик все задания вообще даёт только на джаве, хотя, понятно, они от этого быстрей работать не будут. Тем не менее, даже там каждое решение, помимо корректности, обязательно оценивается по двум критериям - время работы и потреблённая память, и задание не принимается, если хотя бы по одному критерию задание не впишется в лимит. И замечу, что надо сильно попотеть чтобы получить 100% балл за курс. Седжвик так делает
исключительно в учебных целях - для наглядности самого алгоритма и абстрагирования от мелких технических деталей, для чего джава вполне пригодна. Понятно, что после полного понимания алгоритма он может быть реализован на более подходящем языке. Ну это так, оффтоп в защиту Седжвика. Он очень достойный специалист и великолепный профессор.
Zealint писал(а):
Четвёртое. Структура библиотеки. Представьте, что мне нужен синус. Подключается библиотека, в которой кроме синуса ещё полсотни функций, которые мне не нужны. Зачем усложнять компиляцию? Может показаться, что это ничего не усложняет, но на самом деле в крупных проектах, состоящих из огромного количества подключаемых модулей, почти все из которых используются лишь на полпроцента, это имеет свой эффект. Нужно так продумывать структуру библиотеки и самого языка, чтобы подключалось только то, что нужно. Для этого структура должна быть хорошо продуманной.
Я вижу два выхода - радикальный и умеренный. Умеренный заключается в помещении каждой функции в отдельный объектный модуль. Раньше так часто делали статические С-шные библиотеки именно с целью уменьшения кода. Тут есть проблемы – либо геморрой с написанием (плодим тысячи крошечных файлов исходного текста без статических функций/переменных) либо геморрой с устаревшими объектными форматами (т.к. при генерации разных модулей на уровне компилятора обязательно возникнут проблемы со статическими функциями). Разрешение проблемы с умеренным подходом заключается в модернизации объектных форматов (что давно назрело и по другим причинам тоже). Радикальный подход заключается в том, что все языковые и системные библиотеки должны быть реализованы в виде динамически подгружаемых библиотек. Только в этом случае скомпилированный "Hello, World!" сможет иметь размер меньше 50 байт. Но для этого нужна хорошая интеграция языка (компилятора) с операционной системой, иначе каждый 50-байтный "Hello, World!" будет тащить за собой 100-мегабайтные DLL. Лично мне радикальный подход кажется более перспективным, но оба подхода не исключают друг друга.
Zealint писал(а):
Когда мы видим, что одна библиотека ссылается на другую только из-за того, что нам оттуда нужна лишь одна функция, а эта функция требует другую библитеку, а та – третью, то мы получаем ад. Когда нам нужно несколько гигабайт говна из-за того, что понадобилась некоторая функция или возможность. Пример такого говна – концепция Linux ( да-да, забросайте меня гневными воплями : ) Windows тоже говно, так что не расстраивайтесь, равновесие в этой войне достигнуто : ) )
На самом деле развертывание г-на – ещё более масштабный процесс. Здесь мало ссылок на цепочки библиотек. Поистине взрывоподобное увеличение объёма г-на происходит при следующих дополнительных обстоятельствах:
1) Выходят новые версии библиотек. Для совместимости со старыми приложениями система наряду с новыми оставляет некоторые версии старых библиотек (несовместимых по вызовам).
2) Появляются альтернативные версии библиотек, которые по мнению создателей лучше, чем уже существующие, но с совершенно несовместимым API.
3) Функциональность следующего, верхнего уровня использует как одни, так и другие библиотеки (т.к. что-то лучше сделано там, а что-то – сям).
4) Т.к. ряд функций реализованы в виде шаблонов, оказывается, что большое кол-во одних и тех же функций присутствует не только в куче копий пользовательского ПО, но и в библиотеках, которые это ПО использует.
5) Когда объём кода вырастает до размера, превышающего возможность понимания одним программистом, каждый из них вместо использования уже существующей функции (о которой он, может быть, даже не знает) пишет такую же новую (например, в исходниках UEFI Self-Certification Test 2.3
пять разных копий расчёта CRC32 со стандартным полиномом, функционально абсолютно одинаковых). Также вместо изменений в одной функции (эти изменения могут незаметно обрушить всё приложение), программист предпочитает поменять её копию, там где это возможно.
Т.к.
каждый из этих шагов вызывает увеличение кода в разы, совокупный их эффект оказывает экспоненциальное влияние на объём.
Zealint писал(а):
Пятое. Качество. Когда я читаю коды некоторых библиотек или функций, свободно демонстрируемых в интернете, то у меня складывается устойчивое впечатление, что пишут их студенты в рамках своих курсовых работ. Профессионал никогда на напишет такого бреда, какой приходится иногда видеть. Я не преувеличиваю недостаток способностей и опыта, сами посудите, только
10% программистов могут написать бинарный поиск правильно. И, к сожалению, из этих 10% ещё только 10% разбираются в остальных алгоритмах на уровне нормального прилежного студента. Из них ещё 10% способны хорошо кодировать. А из них только 10% делают код не только понятным, но и эффективным. Как-то так.
Вывод парадоксален - тщательная фильтрация и
уменьшение штата сотрудников для ответственных проектов. Иногда один программист может сделать лучше, чем 100 за то же самое время. На самом деле, этот подход проверен практикой и доказал свою справедливость.
Zealint писал(а):
Шестое. Тесты. При создании библиотеки нужно создавать систему тестов, которая тоже должна быть частью библиотеки.
Абсолютно согласен.
Zealint писал(а):
Седьмое. ... Теперь я должен скачать код этого человека, установить все эти библиотеки, которые мне лично нафиг не нужны. Почему так происходит? Потому что нет нормально продуманной стандартной библиотеки ни в одном языке. Библиотека должна быть максимально замкнутой на самой себе (требует только функции из неё же), но при этом каждая функция должна требовать подключения как можно меньшего числа других пакетов библиотеки, когда это не противоречит здравому смыслу.
Поэтому я уверен, что при разработке ЯВУ необходимо включить ряд типов и математических функций (фактически всё, что часто используется, требует высокой производительности и не зависит от ОС) в стандартные языковые библиотеки. Здесь, однако, надо проявлять величайшую осторожность, иначе эти библиотеки мгновенно превратятся в монстра наподобие STL или Boost. Особенную осторожность нужно проявлять при создании шаблонов и отказываться от их использования без крайней необходимости.