LINUX.ORG.RU

ЯП, ОС, архитектура процессоров, инструкции

 , , , ,


1

3

Заглянув за кулисы своего компьютерного мирка, получил кучу мозаичных кусочков.
1. Вот есть у нас процессор со своей архитектурой, будь то X86 или ARM. Под нее портируют компиляторы топовых языков программирования путем использования процессорных инструкций вроде SSE. Что есть оптимизации компилятора? Вот написан код, компилятор его перековеркал для лучшей производительности на определенной архитектуре при использовании тех или иных инструкций процессора. Но всегда ли выбранный компилятором способ коверканья определенного куска кода можно считать оптимальным? Есть оптимизации на потребление оперативной памяти, производительности, размера кода, да что уж там - всяких «волшебных ключиков» просто тьма, успевай только тестировать их. Обилие этих ключиков соединяются в группы оптимизаций по параметрам. ОС пишут на компиляторе ЯП, компилятор завязан на ОС для компилирования других проектов - иначе не было бы таких разделений вроде: «поддерживаемые платформы: MS Windows, Linux, Android» и т.п. Этот список поддерживаемых платформ есть даже у самого компилятора (rust, например). Вот хочу я, например, свой процессор изобрести с уникальной архитектурой, значит ли это, что мне, минимум, придется портировать компилятор того же С? А если написать операционную систему? Ее корень - ядро, его пишут на ЯП, компилятор которого уже завязан на поддерживаемых им платформах (читай: ОС), значит ли это, что написать свое ядро на том же расте невозможно?
2. Еще мне непонятна идея генерируемого кода компиляторами. Пару слов обо мне: шарпист заинтересовался растом, значит попытаюсь понять на его примере. Так вот, у нас есть компилятор раста, который генерирует безопасный исполняемый код. В том же C или C++ генерируется код, но его безопасность исполнения не гарантируется. В C# есть сборщик мусора как решение проблемы предыдущих языков программирования. В расте сборщика мусора нет, т.е. его компилятором генерируется то же самое, что и у C или C++, но в данном случае он безопасный «на слово», в конечном виде он выглядит как и небезопасный результат компиляторов прежних 2-ух ЯП? Или компилятор раста на стадии компиляции проверяет паршивость кода, но при этом то же самое происходит при выполнении программы и от результата какой-нибудь проверки может случиться что-то иначе? Сложновато объяснил, всё сводится к следующему вопросу: какими жертвами удалось добиться безопасности растом?


Ответ на: комментарий от DarkEld3r

«Смотря каких». Под (чего-то стоящими) проверками я подразумевал аналог плюсового at - при простом доступе по индексу раст делает похожие вещи.

Меня интересует та проверка, которая имелась ввиду в оригинальном сообщении:

«Ну а если нам надо пройтись по вектору целиком, то как и в С++ будет одна проверка, а не на каждой итерации.»

sf ★★★
()
Ответ на: комментарий от sf

Меня интересует та проверка, которая имелась ввиду в оригинальном сообщении:

Да я, вроде, ответил? Попробую ещё раз: в расте при «произвольном обращении по индексу» будут дополнительные проверки, ну и паника, если индекс невалидный. Прямо как во всяких менеджед языках. В С++ есть аналог - метод at, но «обычный» доступ по индексу «более быстрый» так как там этой ерунды нет, но и за корректность мы отвечаем сами. При использовании итераторов и в расте и в С++ тоже нет проверок с выбрасыванием исключения.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

При панике деструкторы вызываются и память освобождается

Всегда думал, что течет тут память. Сейчас проверил, действительно вызываются.

Aswed ★★★★★
()
Ответ на: комментарий от DarkEld3r

Спрошу то же самое в поседний раз :) Меня интересует только случай итераторов.

> > [1] Меня интересует та проверка, которая имелась ввиду в оригинальном сообщении:
> [2] Ну а если нам надо пройтись по вектору целиком, то как и в С++ будет одна проверка, а не на каждой итерации.
[3] Да я, вроде, ответил? ... При использовании итераторов и в расте и в С++ тоже нет проверок с выбрасыванием исключения.

[2] намекает, что какая-то одна волшебная проверка (не относящаяся к какждой итерации) всё еще осталась. Или [3] - это «ответ», что их уже стало 0?

sf ★★★
()
Ответ на: комментарий от anonymous

Я не называл _ничего_ контролем над исполнением.

Я сказал что в C все вызовы функций являются _явными_ вызовами функций. В других языках, _например_, С++ операторы могут транслироваться не только в голый объектный код но и во внешние вызовы. И тут уже нужно знать тонкости языка и каждый раз отдавать себе отчет о том что будет делать транслятор. Джоель Спольски назвал это дырявыми абстракциями.

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

German_1984 ★★
()
Ответ на: комментарий от German_1984

Но это не так. Все это

В В си полно «вызовов», которые на самом деле макросы. В си полно вызовов функций, которые приводят к вызовам других функций, причём это не так гибко настраивается, как в c++, с его выбором аллокаторов, наборов свойств(traits) и пр. приёмов.

Никакой разницы с си у c++ при трансляции нет, кроме трансляции имён(т.к. неймспейсы, перегрузка функций и пр.). Какой-то левый код могут добавлять разве что исключения(отключаемые, надо заметить) и rtti(так же отключает). Все остальное тривиально транслируется(в том числе и vtbl).

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

С чего ты взял, что си более популярен для низкоуровневых вещей?

Что значит максимально отделяет стандартную библиотеку от транслятора? У C++ та же ситуация.

anonymous
()
Ответ на: комментарий от anonymous

Что значит максимально отделяет стандартную библиотеку от транслятора?

Все конструкции языка транслируются либо непосредственно в машинный/объектный код либо во внешние вызовы - функции ОС или библиотек.

В С (и только в нем из известных мне языков) ни один оператор не транслируется во внешний вызов. Это сильно облегчает портирование С на разные платформы.

С чего ты взял, что си более популярен для низкоуровневых вещей?

Это ответ на комментарий ТС'а:

Теперь понятно доминирование C в системном программировании - он везде.

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

Я об этом и говорю. Если мы программируем микроконтроллер и ограниченными ресурсами то многие шаблоны stl потекут. И при написании ядра ОС тоже есть своя специфика в выделении и освобождении памяти.

German_1984 ★★
()
Ответ на: комментарий от German_1984

Я сказал что в C все вызовы функций являются _явными_ вызовами функций.

За макросом может скрываться хоть 100500 вызовов функций. Причём макросы можно именовать как угодно, в том числе, неотличимо от функций.

И тут уже нужно знать тонкости языка и каждый раз отдавать себе отчет о том что будет делать транслятор.

Так себе аргумент, имхо. Если у нас каждый байт и каждая миллисекунда на счету, то точно так же можно позвать сишную функцию из библиотеки, а она «внезапно» выделит кучу памяти и будет выполняться полчаса. То есть «детали реализации», в таких случаях, всегда знать надо. Ну а вообще есть профайлер, так что это не такая и проблема.

При этом в С++ есть абстракции, которые (почти) ничего не стоят в рантайме.

DarkEld3r ★★★★★
()
Ответ на: комментарий от sf

Спрошу то же самое в поседний раз :)

Для начала ответь на один вопрос - ты правда не понял мою мысль или цепляешься к словам?

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Я не о стоимости по времени или памяти говорю а о наличии/отсутствии внешних зависимостей. ТС, вроде как, хочет ядро ОС писать, а там со внешними зависимостями не слишком хорошо дела обстоят.

German_1984 ★★
()
Ответ на: комментарий от anonymous

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

Iron_Bug ★★★★★
()
Ответ на: комментарий от German_1984

Я сказал что в C все вызовы функций являются _явными_ вызовами функций. В других языках, _например_, С++ операторы могут транслироваться не только в голый объектный код но и во внешние вызовы.
В С (и только в нем из известных мне языков) ни один оператор не транслируется во внешний вызов.

Какой ты наивный. Вот тебе сишный код, в котором вызовы операторов транслируются во внешние вызовы: http://goo.gl/PWrr0z . Аналогично, операторы над _Atomic и _Thread_local могут транслироваться нетривиально. Ну и самый очевидный пример - сложение над uint8_t и double транслируется в совсем разный код, хотя и выглядит одинаково. Вывод - в чистом С точно так же присутствует перегрузка операторов, просто она расширяется не программистом, а раз в 10 лет с каждым новым стандартом.

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

nonimous
()
Ответ на: комментарий от erzent

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

anonymous
()
Ответ на: комментарий от German_1984

В С (и только в нем из известных мне языков) ни один оператор не транслируется во внешний вызов.

В С вместо продвинутых операторов (которые есть функции) вызываются функции руками. Вот и вся разница. Хотя иногда вместо функции постоянно пишется руками код, что еще хуже. Тут был как-то эпичнейший топик, как правильно на С сделать s1 + s2.

Шок от С. Как склеивать строки?

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

Это сильно облегчает портирование С на разные платформы.

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

Я об этом и говорю. Если мы программируем микроконтроллер и ограниченными ресурсами то многие шаблоны stl потекут

Они будут работать точно так же, как и glib, например. Тебе надо готовая библиотека - ты ее берешь, она слишком жирная или медленная для определенных условий - ты ее не берешь. Все просто.

anonymous
()
Ответ на: комментарий от nonimous

Какой ты наивный. Вот тебе сишный код, в котором вызовы операторов транслируются во внешние вызовы: http://goo.gl/PWrr0z .

Отличный пример. Компилятор вообще может из кода родить совсем не то, что ты ожидаешь увидеть - что-то выкинуть, что-то «переделать», что-то неявно добавить. И у того же gcc есть масса опций для этого.

anonymous
()
Ответ на: комментарий от erzent

а что делать?
вообще, GPU программируются как обычные FPGA. по сути, это матрицы, на них есть нетлисты, а на них сверху уже мультиплексоры. а на мультиплексорах всякое прочее (имитация шины, «байты», регистры для вычислений и т.д.). на них уже пишутся микрооси, а на этих микроосях уже работают некоторые скриптообразные «языки программирования». вот как это выгдяит, если смотреть со стороны разработчика железа. так что та фигня, которую конченный юзер бодро пишет в своём псевдокодогенераторе - это цветочки по сравнению с той работой, которая уже была проделана.

Iron_Bug ★★★★★
()
Ответ на: комментарий от erzent

Поразительная глубина анализа.

anonymous
()
Ответ на: комментарий от Iron_Bug

GPU программируются как обычные FPGA

Абсолютно ничего общего.

вот как это выгдяит, если смотреть со стороны разработчика железа

Степень чуши просто зашкаливающая.

anonymous
()
Ответ на: комментарий от anonymous

на FPGA можно написать всё. в том числе и GPU. и даже пишут:
http://www.youtube.com/watch?v=oOUmi5p9jak
http://www.kickstarter.com/projects/725991125/open-source-graphics-processor-gpu
кстати, где-то у меня тестовая платка альтеровская валялась. я с ней игралась одно время.
многие процессоры при разработке моделируют на FPGA, потому что прежде чем печатать чип, надо его проверять.

Iron_Bug ★★★★★
()
Ответ на: комментарий от erzent

ты уверен, что все те

300 мб

это именно драйвер? по меньшей мере у невидии точно не только драйвер.

CryAngel
()
Ответ на: комментарий от Iron_Bug

на FPGA можно написать всё. в том числе и GPU. и даже пишут:

Рыжий Вася - идиот. Следовательно, все рыжие - идиоты, а все идиоты - рыжие, и зовут их Васями.

GPU - не FPGA. Ни разу. Никаким боком. Даже по самой сильной пьяни, никакой общей семантики не найдешь.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.