Комментарии 37
И, после его запуска система становится виртуализированной или что происходит?
+7
В систему встраивается гипервизор, как и любой другой, к примеру Hyper-V, обычно на Ring-1 уровня ядра.
0
Так он встраивает себя внизу под уже работающей ОС?
Как проявляется вообще его присутствие?
Как проявляется вообще его присутствие?
+2
Насколько видно из описания проекта — никак не проявляется, автор выложил сам гипервизор, показал как его устанавливать, а дальше дело за теми, кто захочет его использовать и в каких целях.
+1
т.е. ничего не происходит. Просто какой-то код работает на низком уровне и не падает. Отлично
+13
Объясните чо с этим делать теперь
0
Это тот случай, когда говорят "если вы задаёте этот вопрос, то вам не нужен ответ".
Это — просто полуфабрикат. Поверх него можно сделать кучу интересных вещей. Но сам по себе… Как уже сказали: Ничего не происходит. Просто какой-то код работает на низком уровне и не падает. Отлично. — это достаточно полное описание происходящего. Причём последнее слово там к месте: подобную штуку самому, с нуля, по докам — написать достаточно сложно.
Это — просто полуфабрикат. Поверх него можно сделать кучу интересных вещей. Но сам по себе… Как уже сказали: Ничего не происходит. Просто какой-то код работает на низком уровне и не падает. Отлично. — это достаточно полное описание происходящего. Причём последнее слово там к месте: подобную штуку самому, с нуля, по докам — написать достаточно сложно.
+3
А почему малое количество строк на ассемблере преподносится как преимущество? Я всегда считал что asm используется для максимальной производительности. Все уже совсем не так?
+1
Код на асме оч сложно портировать (к примеру, на другие архитектуры), к тому же сейчас компиляторы гораздо лучше оптимизируют, чем это сделал бы человек. Ну и человекопонятность кода.
+3
Спасибо за ликбез!
0
А зачем там вообще ассемблер тогда?
0
к тому же сейчас компиляторы гораздо лучше оптимизируют, чем это сделал бы человекУвы, но это неправда. Такого — даже и близко нету.
Все компиляторы, даже самые современные оптимизируют между «ужас как плохо» и «это такой ужас, что у меня больше нет слов, одни эмоции».
Однако при этом иногда смотришь на код, который они выдают — и просто офигеваешь: это же просто гениально! Откуда это? А это значит — ваша задача хорошо «легла» на какой-то паттерн, который часто встречается и потому кто-то из разработчиков компилятора придумал как это место особо хорошо сделать. Разработал соответствующий ассемблерный кусок и вшил в компилятор. А так как разработчиков компилятора много (тысячи если считать всех, сотни — если только тех, кому за разработку денег платят), то случается это довольно часто. Но достаточно чуть-чуть изменить исходный код — и всё: пиши пропало.
На самом деле, конечно же, человек действует так же (особенно если не гнушаться тем чтобы посмотреть на то, как компилятор решает ту или иную проблему — очень полезно, особенно если вы мало работали с той или иной архитектурой), однако «сведение» задачи к известным паттернам человек делает намного, намного лучше.
Ну и вторая проблема: человек, в общем, выдаёт порядка 30-50 строк отлаженного кода в день. Неважно — на каком языке. Если язык компактный (Haskell какой-нибудь) это может быть чуть меньше, если очень «расхлябанный» (Java или ассемблер) — чуть больше, но в общем, разница от минимума до максимума для одного и того же человека — раза 2-3, не больше.
Однако одной строке на C соответствуют десятки строк ассемблера! То есть с гипервизором на C проще и быстрее работать. Ну и переносимость — хотя это не всегда важно.
+2
Ну если задача одновременно "не легла" и является критичным местом, то переписать её на ассемблере — вполне реально. Писать же на ассемблере всё — оверкилл, куча времени и денег.
При этом те самые известные паттерны, встроенные в компилятор, писали программисты уровнем гораздо выше среднего. Количество программистов способных решить небанальную задачу на асме лучше компилятора невелико.
При этом те самые известные паттерны, встроенные в компилятор, писали программисты уровнем гораздо выше среднего. Количество программистов способных решить небанальную задачу на асме лучше компилятора невелико.
0
Количество программистов способных решить небанальную задачу на асме лучше компилятора невелико.Как раз наоборот: количество программистов, неспособных решить небанальную задачу хуже компилятора невелико. И чем «небанальнее» задача — тем их меньше.
Простейший пример:
Пример на C
Для вас действительно проблема написать что-нибудь вот такое:$ cat test.c #define Old_O_DIRECTORY 00040000 #define Old_O_NOFOLLOW 00100000 #define Old_O_DIRECT 00200000 #define Old_O_LARGEFILE 00400000 #define O_DIRECTORY 00100000 #define O_NOFOLLOW 00040000 #define O_DIRECT 00400000 #define O_LARGEFILE 00200000 int bar(const char *pathname, int old_flags); int foo(const char *pathname, int old_flags) { const int kUnstableFlags = Old_O_DIRECTORY | Old_O_NOFOLLOW | Old_O_DIRECT | Old_O_LARGEFILE; int new_flags = old_flags & ~kUnstableFlags; if (old_flags & Old_O_DIRECTORY) { new_flags |= O_DIRECTORY; } if (old_flags & Old_O_NOFOLLOW) { new_flags |= O_NOFOLLOW; } if (old_flags & Old_O_DIRECT) { new_flags |= O_DIRECT; } if (old_flags & Old_O_LARGEFILE) { new_flags |= O_LARGEFILE; } return bar(pathname, new_flags); } $ ./clang -c -O3 -S test.c -o- .text .file "test.c" .globl foo .align 16, 0x90 .type foo,@function foo: # @foo .cfi_startproc # BB#0: movl %esi, %eax andl $-245761, %eax # imm = 0xFFFFFFFFFFFC3FFF leal (%rsi,%rsi), %ecx movl %ecx, %edx andl $32768, %edx # imm = 0x8000 orl %edx, %eax shrl %esi movl %esi, %edx andl $16384, %edx # imm = 0x4000 orl %eax, %edx andl $131072, %ecx # imm = 0x20000 orl %ecx, %edx andl $65536, %esi # imm = 0x10000 orl %edx, %esi jmp bar # TAILCALL .Lfunc_end0: .size foo, .Lfunc_end0-foo .cfi_endproc .ident "clang version 3.8.243773 " .section ".note.GNU-stack","",@progbits
Пример на ASM
.globl foo .align 16, 0x90 .type foo,@function foo: .cfi_startproc movl %esi, %eax movl %esi, %ecx andl $0xfffc3fff, %esi andl $0x00014fff, %eax andl $0x00028fff, %ecx shl %eax shr %ecx orl %eax, %esi orl %ecx, %esi jmp bar .Lfunc_end0: .size foo, .Lfunc_end0-foo .cfi_endproc
Да никогда в жизни не поверю!
Проблема в другом: смени я эти константы — и всё: компилятор породит что-то более-менее приличное всё равно, а человеку потребуется надо всем этим голову заново ломать! А если создать код на ассемблере, где эти константы менять можно — то да, версия на C будет лучше, потому что она не так «заточена» под конкретные условия.
Вот в этом и беда: человек может писать на ассеблере лучше, чем компилятор. Почти любой человек лучше почти любого компилятора. Проблема в другом. Проблема в том, что вы лишаетесь гибкости: как только задача чуть-чуть меняется вам всё приходится переделывать. Про перенос на другой процессор я уже вообще молчу, но даже небольшое изменение начальных условий превращается в муку.
0
Для по-настоящему сложных систем команд типа ARM со сдвигами и хитрой организацией констант компилятор действительно побеждает человека, и намного проще подсказать ему некоторые особенности, чам переписывать на ассемблере.
0
Да ладно вам. Возьмите тот же самый пример посмотрите что вам напорождает компилятор:
Сделать код лучше сможете сами или мне показать?
Проблема, собственно, та же, что в примере выше: компилятор не понимает логики программы — и потому генерит "лажу". Про "хитрую организацию констрант" — тоже мимо: во-первых она на ARM'е не такая и хитрая (вот Thumb'е — да, там есть странные варианты), а во-вторых — она далеко не всегда мешает, а уж использовать её "с пользой" компилятору удаётся реже, чем человеку обычно (хотя, как я уже говорил: нарвётесь на заранее кем-то придуманный код — можете быть приятно удивлены).
Насчёт же "проще подсказать некоторые особенности"… да, я знаю как переделать этот пример так, чтобы компилятор сгенерировал оптимальный (или почти оптимальный) код. Но можно ли это сказать, что это "подсказка некоторых особенностей"? Если там нужно, в том числе, ещё и "ни на что не влияющие" скобочки правильно расставить, чтобы "всё срослось"?
Это уже не компилятор генерит оптимальный код, это я его генерю — но через посредника. А он точно в этом случае нужен? Может проще как-нибудь напрямую?
Вот вам ARM
$ ./clang --target=arm-eabi-elf -S -O3 test.c -o- ... .type foo,%function foo: @ @foo .fnstart @ BB#0: mov r3, #32768 mov r2, #16384 and r12, r2, r1, lsr #1 and r3, r3, r1, lsl #1 bic r2, r1, #245760 orr r2, r3, r2 mov r3, #131072 orr r2, r2, r12 and r3, r3, r1, lsl #1 orr r2, r2, r3 mov r3, #65536 and r1, r3, r1, lsr #1 orr r1, r2, r1 b bar .Lfunc_end0: .size foo, .Lfunc_end0-foo .cantunwind .fnend
Сделать код лучше сможете сами или мне показать?
Проблема, собственно, та же, что в примере выше: компилятор не понимает логики программы — и потому генерит "лажу". Про "хитрую организацию констрант" — тоже мимо: во-первых она на ARM'е не такая и хитрая (вот Thumb'е — да, там есть странные варианты), а во-вторых — она далеко не всегда мешает, а уж использовать её "с пользой" компилятору удаётся реже, чем человеку обычно (хотя, как я уже говорил: нарвётесь на заранее кем-то придуманный код — можете быть приятно удивлены).
Насчёт же "проще подсказать некоторые особенности"… да, я знаю как переделать этот пример так, чтобы компилятор сгенерировал оптимальный (или почти оптимальный) код. Но можно ли это сказать, что это "подсказка некоторых особенностей"? Если там нужно, в том числе, ещё и "ни на что не влияющие" скобочки правильно расставить, чтобы "всё срослось"?
Это уже не компилятор генерит оптимальный код, это я его генерю — но через посредника. А он точно в этом случае нужен? Может проще как-нибудь напрямую?
0
Компилятор умеет LTO. Например, если O_DIRECT — это единственный флаг который может быть на входе, то код метода сокращается до двух инструкций. А вот человеку будет тяжело вспомнить в каких файлах какие флаги использовались, и что функция которая использует другие флаги нигде не вызывается и может быть исключена.
0
Это, как бы, то, с чего мы начинали:
Компилятор просто сможет обработать большие объёмы кода быстрее, чем человек. Человеку зачастую требуется так много версии на "вылизывание" и "подгонку" метода под конкретные условия, что железяку соотвествующую успевают снять с производства. Так что если вы не под Вояджер программу пишите (где железо будет 40 лет неизменным ввиду физической невозможности его заменить), то вы просто не успеете воспользоваться совершенством "человеческого" кода. Но что он будет лучше — несомненно. LTO там или ГТО.
Ну и вторая проблема: человек, в общем, выдаёт порядка 30-50 строк отлаженного кода в день. Неважно — на каком языке. Если язык компактный (Haskell какой-нибудь) это может быть чуть меньше, если очень «расхлябанный» (Java или ассемблер) — чуть больше, но в общем, разница от минимума до максимума для одного и того же человека — раза 2-3, не больше.
Компилятор просто сможет обработать большие объёмы кода быстрее, чем человек. Человеку зачастую требуется так много версии на "вылизывание" и "подгонку" метода под конкретные условия, что железяку соотвествующую успевают снять с производства. Так что если вы не под Вояджер программу пишите (где железо будет 40 лет неизменным ввиду физической невозможности его заменить), то вы просто не успеете воспользоваться совершенством "человеческого" кода. Но что он будет лучше — несомненно. LTO там или ГТО.
-1
Назвать ваш пример небанальной задачей язык не поворачивается. Имелось ввиду что-то посложнее.
Попробуйте написать ту же нейронную сеть лучше компилятора. ;)
Попробуйте написать ту же нейронную сеть лучше компилятора. ;)
0
Да легко. Берёте вывод "clang -O3 -S" и смотрите где его улучшить. Уверяю вас — там будет куча мест, где это можно сделать. И чем сложнее будет задача — тем их будет больше.
Вопрос, как я уже сказал, во времени, больше ни в чём.
Вопрос, как я уже сказал, во времени, больше ни в чём.
0
А смысл? Делайте тогда ассемблерные вставки где надо. А самостоятельно полностью вы не напишете лучше, я почти уверен в этом. А если и напишете — вы один из немногих.
0
А самостоятельно полностью вы не напишете лучше, я почти уверен в этом.
Дурацкий вопрос: вы это сами пробовали проделывать или сейчас тут только руками махаете?
Я — пробовал. Долго — это да, тут и говорить не о чем. Но несложно. Современные компиляторы всё ещё генерят довольно-таки "рыхлый" код — и вышеуказанного примера вполне достаточно для того, чтобы примерно понять — когда и почему.
А смысл?А вот это — нужно в каждом случае решать отдельно. Да, писать на ассемблере — долго и зачастую невыгодно. Просто времени и сил уходит на порядок больше, чем если писать то же самое на C и на два и более порядка — чем если писать на языках более высокого уровня.
Но это, согласитесь, совсем другой довод, чем тот, с которого мы начали. Да, от самых страшных вещей компиляторы научились избавляться (обратите внимание на то, что в описанном примере компилятор пидумал-таки как обойтись без условных переходов — а это, в общем-то, самое главное при использовании современным CPU), но говорить о том, что «компиляторы гораздо лучше оптимизируют, чем это сделал бы человек» — увы, несколько преждевременно. Это если сказать мягко.
P.S. Та же самая ситуация и «ниже», кстати: AMD пользуется HDL-компиляторами при извотовлении своих CPU, а Intel — много разводит «руками». Но происходит это не потому, что «компиляторы ща умные — вастче». А просто потому, что на «ручную» разводку у AMD ресурсов не хватает. Результат — всем известен, не так ли? С другой стороны если некому приличную архитектуру сделать, но никакая «ручная разводка» и «написание на ассемблере» не спасут. Пример — те же AMD и Intel, но уже в области разработки GPU :-)
0
Вопрос был в том, какой смысл брать вывод компилятора и улучшать его в качестве ассемблерной программы вместо того чтобы делать в ней ассемблерные вставки. С самого начала я об этом и говорил — неудачные куски можно переписать на асме в качестве вставок в С код.
Какую самую сложную задачу вы реализовали полностью на асме? Какой был её размер? Несколько быстрее это вышло, чем оптимизированный код на С?
Какую самую сложную задачу вы реализовали полностью на асме? Какой был её размер? Несколько быстрее это вышло, чем оптимизированный код на С?
0
Какую самую сложную задачу вы реализовали полностью на асме?Интерпретатор байткода.
Какой был её размер?Порядка 100'000 строк на асме. Аналог на C был примеро в 20'000 строк.
Несколько быстрее это вышло, чем оптимизированный код на С?Сильно зависит от компилятора. GCC/Clang примерно вдвое удалось обогнать, а MSVC 2010 — вчетверо (сейчас не знаю, может он получше стал).
Почти все «трюки», которые применялись — были как раз подобного рода: человек может заметить, что он может одной инструкцией породить две, а то и три вещи, а компилятор на это неспособен.
Думаю что можно было бы «помочь компилятору» и сотворить такие структуры, которые он смог бы обратить в код близкий к написанному руками (примерно как в игрушечном примере выше). Одна беда: это ещё сложнее и дольше, чем писать сразу на ассемблере, а выигрыш, в общем, нулевой (на другую архитектуру трюки, скорее всего не лягут, а «провернуть фарш назад» и придумать как заставить компилятор породить-таки нужный тебе код на ассемблере — та ещё работёнка).
Но да, все задачи в таком режиме решать не будешь: разработка заняла примерно раз в 10 больше времени, чем вариант на C, а ускорение — всего лишь вдвое (а на языках более высокого уровня, чем C было бы ещё быстрее писать и оно бы ещё медленнее работало).
Чудес в мире не бывает, увы.
-1
А если бы вы в тех 20000 строк на Си выбрали самые частоиспользуемые и неоптимизированные места и сделали там ассемблерные вставки (получив, например, 18000 строк Си + 10000 асм и потратив в 2 раза больше времени чем на чистый Си)? Позволю себе предположить, что ускорение было бы раза в 1.5, а то и больше.
О том и речь — чистый асм не имеет смысла. Слишком много в любом коде редкоиспользуемых, некритичных или нормально оптимизируемых компилятором мест. Смысла писать их на асме вместо Си — 0. Ассемблерные вставки не такая уж и редкость, а вот чистый асм можно сдавать в музей.
О том и речь — чистый асм не имеет смысла. Слишком много в любом коде редкоиспользуемых, некритичных или нормально оптимизируемых компилятором мест. Смысла писать их на асме вместо Си — 0. Ассемблерные вставки не такая уж и редкость, а вот чистый асм можно сдавать в музей.
0
Хорошо, небольшой фикс — "компиляторы оптимизируют эффективней за единицу времени". :) Понятно, что человек может вылизать код до идеального состояния, но трудозатраты на это слишком велики. Тогда как компилятор в большинстве случаев выдаст относительно нормальный код, который может быть и не будет идеальным, но будет вполне рабочим и относительно эффективным, при этом за очень хорошие показатели времени.
0
На самом деле, очень интересно. Надо попробовать загрузить через этот супервизор 2 ОС одновременно. Всегда хотел возможность переключиться в полноценную виндовз, с полноценной GPU, при этом не выключая linux base os
0
Всегда хотел возможность переключиться в полноценную виндовз, с полноценной GPU, при этом не выключая linux base osGPU passthrough же!
0
пробовал, стабильных решений не нашел
0
С 2014-го на основной рабочей станции именно так построено всё.
Arch Linux, KVM, LVM Thin Provisioning, GTX 1070. Да, видеокарта одна!
Нужна поддержка VT-d на проце, и IOMMU на плате. На видухе должна быть UEFI прошивка.
Win10, Win8 для разработки и отладки отлично работают. Для игр и прочих графических задач была Win10. Выдавала на 3-5% меньше от производительности хоста по процу и видео, если без всяких «фиксов» мелтдаунов и спектров, которые от производительнсти тыкву оставляют.
По диску чуть похуже. Самое лучшее, что смог выжать, это из 100к гостевых IOPS из 500к хостовых. Это из-за thin provisioning, без него процентов 10 потерь. Но он, сука, удобный!
С семёркой была беда какая-то. Она как-то криво с уефи работает, поэтому уефи прошивка видеокарты не хотела грузиться с пробросом. Просто чёрный экран. Про XP можно не говорить, он UEFI не умеет. Но для тестирования и без проброса хватает.
Всё это заключается в нескольких скриптах на баше, колдунства с выгузкой/загрузкой модулей видеокарты, консоли, перебросом модулей драйверов юсб, звука и прочих необходимых в госте устройств на прокси-модули vfio.
Чтобы вернуться в хост из гостя, когда видеокарта только одна, как у меня, отдельный USB-хост должен поддерживать операцию reset. Иначе ядро резетит всё подряд, что иногда вгоняет его в панику. Но у меня поддерживается резет, поэтому особо не парился.
Arch Linux, KVM, LVM Thin Provisioning, GTX 1070. Да, видеокарта одна!
Нужна поддержка VT-d на проце, и IOMMU на плате. На видухе должна быть UEFI прошивка.
Win10, Win8 для разработки и отладки отлично работают. Для игр и прочих графических задач была Win10. Выдавала на 3-5% меньше от производительности хоста по процу и видео, если без всяких «фиксов» мелтдаунов и спектров, которые от производительнсти тыкву оставляют.
По диску чуть похуже. Самое лучшее, что смог выжать, это из 100к гостевых IOPS из 500к хостовых. Это из-за thin provisioning, без него процентов 10 потерь. Но он, сука, удобный!
С семёркой была беда какая-то. Она как-то криво с уефи работает, поэтому уефи прошивка видеокарты не хотела грузиться с пробросом. Просто чёрный экран. Про XP можно не говорить, он UEFI не умеет. Но для тестирования и без проброса хватает.
Всё это заключается в нескольких скриптах на баше, колдунства с выгузкой/загрузкой модулей видеокарты, консоли, перебросом модулей драйверов юсб, звука и прочих необходимых в госте устройств на прокси-модули vfio.
Чтобы вернуться в хост из гостя, когда видеокарта только одна, как у меня, отдельный USB-хост должен поддерживать операцию reset. Иначе ядро резетит всё подряд, что иногда вгоняет его в панику. Но у меня поддерживается резет, поэтому особо не парился.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
На GitHub опубликован исходный код компактного гипервизора