|
|
||||||
Перевести код С++ в код на Ассемблере (Ассемблерная вставка для С++)19.04.2017, 17:10. Показов 3771. Ответов 20
Метки нет (Все метки)
Приветствую знатоков!
Трудоемко ли перевести код функции Func под ассемблерную вставку (в Visual Studio через __asm (?)) Код на С++ прилагаю. Будет ли прирост производительности?
0
|
||||||
| 19.04.2017, 17:10 | |
|
Ответы с готовыми решениями:
20
Ассемблерная вставка в MVS для нахождения максимального элемента массива Переписать код на ассемблере Ассемблерная вставка в код на C++ |
|
Модератор
|
||
| 19.04.2017, 23:03 | ||
|
Если вопрос
Т.к. современные компиляторы (особенно от MicroSoft и в большей степени от Intel) оптимизируют код до неузнаваемости. И в реалии могут не создавать переменные в памяти, используя регистры. Т.е. то, на чём можно было получить ускорение раньше. Прирост может получиться при использовании расширенных команд процессора SIMD - для обработки массивов одной командой - т.е. удалением циклов. Но наибольший прирост даёт изменение алгоритма. Обработка целочисленного массива: заполнение по формуле, вычисление суммы, изменение элементов по правилу. Ну и вообще, поискать по разделу AVX, SSE и прочее.
0
|
||
|
1719 / 568 / 187
Регистрация: 12.03.2016
Сообщений: 2,169
|
||||
| 20.04.2017, 00:48 | ||||
|
Пробовал как и обещал ТС перевести это все на AVX (с горяча, когда еще не разбирался в алгоритме), но с таким количеством циклов и проверок приходится все делать через такие костыли что вся прелесть AVX махом улетучивается. Становится еще хуже, да и программа увеличится до неизвестных размеров. bedvit, Вы же не зря компилировали ее (прога в C#) в "Сборка Debug x64" и получили самый быстрый результат. То же самое получается (чуть быстрее работает) если компилировать прогу c++ в "Release x64". Только в плюсах она получается в 32 кило, а у Вас в 7. Лазить по ним отладчиком что бы узнать в чем разница и что там компилятор напихал вряд ли кто будет. Единственное что при отладке, как и советовал nmcf, пробежался по дизассемблированному коду. Как и ожидалось компилятор использовал 64 битные регистры (не FPU, mmx, sse и т.д), а именно 64 разрядные, так как посчитал, что для переменных long long это будет самый оптимальный вариант. Единственное чтобы предложил - это написать данную функцию на ассемблере для 64 регистров и присоединить получившийся объектник к проекту. (Читал, что использовать 64 битные регистры в ассемблерных вставках нельзя, но сам еще не сталкивался). Но думаю, как и сказал ФедосеевПавел, прирост в производительности будет незначительный. Да и объектник в проект C#, наверное вставить можно. Если да, то сравнивать эти два языка на данном примере вообще будет лишено смысла.
3
|
||||
|
|
||
| 20.04.2017, 10:52 [ТС] | ||
|
мановар, благодарю за проделанную работу!
Ссылка на тему проекта. В текущей теме нет цели сравнивать языки, здесь ТС хотелось бы понять эффективность ассемблерной вставки на конкретном примере, заодно и получить новые знания в этом направлении. Ассемблерную вставку вставить в С++ - можно, в С# - нельзя, но можно подключить неуправляемую dll (ИМХО) Какой профит тогда от ассемблерных вставок? если можно на С++ указать компилятору на макс. оптимизацию в настройках проекта, а в С# работать через небезопасный код (unsafe) . Добавлено через 11 минут ФедосеевПавел, а компилятор Microsoft Visual Studio 2017 для С++ насколько хорошо оптимизирует код, в сравнении с вами описанными (возможно у вас есть информация)? судя по результатам мановар, используются 64 разрядные регистры, но в не оптимальном виде?
0
|
||
|
197 / 89 / 15
Регистрация: 10.07.2016
Сообщений: 146
|
|
| 20.04.2017, 16:51 | |
|
Какая-то мелкая программулинка и если указанные выше компиляторы выдают 7 и даже 32 кб, остаётся только громко улыбнуться таким оптимизациям
0
|
|
|
1719 / 568 / 187
Регистрация: 12.03.2016
Сообщений: 2,169
|
|
| 20.04.2017, 19:36 | |
|
0
|
|
|
Модератор
|
|
| 21.04.2017, 22:14 | |
|
А я правильно понимаю, что в тексте a[i] - это отсортированный массив кубов целых чисел. Может быть организовать поиск в нём не последовательным просмотром (строка 15), а бинарным поиском. Помню, на задаче "ожерелье" при помощи перебора - это кардинально сокращало время.
Добавлено через 2 минуты А на размер итогового exe не смотрите. Сам код в этом файле может занимать не очень много места (при маленьких программах). Добавлено через 6 минут Да и в строках 22-25 вижу последовательный перебор - опять напрашивается двоичный поиск. Причём, если можно до начала поиска оценить левую и правую границы - можно это использовать.
1
|
|
|
Asm/C++/Delphi/Py/PHP/VBA
|
||||||
| 22.04.2017, 13:30 | ||||||
|
bedvit, хорошо бы посмотреть листинг получаемого кода на ассемблере, тогда, вероятно, будет проще найти места, которые можно оптимизировать.
Например, вот это: unsigned long long z = x * 12599/10000; наверняка можно оптимизировать через замену на unsigned long long z = x * 82570/65536; (или unsigned long long z = x * 82570 >> 16;). Да, именно 82570, а не 82569, так будет даже точнее.Слишком сильно не углублялся, но можно попытаться сам алгоритм ещё оптимизировать (хорошо, если бы ты его описал словами). Можно попытаться сделать так, чтобы потоки, выполняющие вычисления, выполняли обращения как можно к более смежным участкам памяти (для оптимизации использования кэша). Добавлено через 9 минут Кстати, участок деления на асме можно написать ещё точнее и с меньшим кол-вом сдвигов (т.е. быстрее):
Добавлено через 3 минуты А ещё быстрее будет, если между mov и mul, а также между mul и shld + между shld и mov будет что-то вставлено, не меняющее eax и edx, тогда эти инструкции могут быть спарены с другими. Скажем, разбавить этот код предыдущими строками (ax = , r = , while...)
1
|
||||||
|
|
|||||||
| 24.04.2017, 13:13 [ТС] | |||||||
|
ФедосеевПавел, все правильно понимаете.
Для лучшего понимания, поясню для чего всё это ![]() Первичная задача - рассчитать переменные для решения уравнения x ^ 3 + y ^ 3 = z ^ 3 - 1 в задаваемом диапазоне (натуральные числа). Реализация: Мах. границу диапазона вводит пользователь - только натуральные числа (минимальная всегда 1). Далее строится массив (вектор) степеней этих чисел (до макс.границы). Далее в отдельных потоках (зависит от количества лог. ядер ЦП), запускается числодробилка -Func(), которая из этого массива/вектора подбирает варианты когда они удовлетворяют уравнению и выводит в консоль (в main() переменные не возвращаются, но есть глобальные переменные - общие для потоков) Ветка с зеркальными вариантами х,у обрезается. Обрезаются итерации - которые заведомо не дадут нужного результата. Каждый поток считает с шагом по массиву/вектору числа самих потоков - threadsN (очень хорошо и равномерно парраллелится). вот алгоритм на С++ Кликните здесь для просмотра всего текста
т.к. 99% вычислений - это числодробилка (функция Func), то её и решил оптимизировать с помощью ассемблерной вставки (пишу в visual studio) unsigned long long z = x * 12599/10000 - отсекает заведомо лишние ветви вычислений (сжимая область поиска в массиве/векторе). Jin X, по причине своих небольших знаний в данном направлении, понял в вашем сообщении не всё , но главное понял - то, что оптимизировать можно - и уже за это вам спасибо! Осталось понять, что можно оптимизировать, если посмотреть на первоначальную цель, и полный алгоритм. Добавлено через 20 минут Могу написать комментарии построчно к коду.
0
|
|||||||
|
Asm/C++/Delphi/Py/PHP/VBA
|
||
| 24.04.2017, 20:06 | ||
|
Компилятор в VS проводит оптимизацию довольно чётко и обойти его в подобных задачах не так просто. Можно элементарно проваливаться, не учтя что-то, что он учёл ![]() Скажем, замена деления (12599/10000) заметно скорость не увеличит, т.к. это самый внешний цикл, он выполняется относительно малое кол-во раз. Оптимизировать тут можно, скорее, алгоритм. Например, придумать такой вариант, когда можно использовать SSE2, чтобы работать сразу с несколькими числами параллельно. Или сделать так, чтобы память использовалась небольшими участками (может, и сейчас так, не знаю, надо углубляться в алгоритм). Т.е. у нас массив, скажем, из 100 000 чисел. Если мы будет обращаться к нему хаотично, то очень часто будут возникать промахи процессорного кэша (т.к. весь массив в 800 Кб просто не уместится в него... по крайней мере, в L1 и L2). А если обработать сначала 1000 элементов (и больше к ним никогда не возвращаться!), затем ещё 1000 и т.д. (причём, всеми потоками, а не каждым обращаться к разной памяти... ну или раздробить на меньшие блоки, по 256 чисел... хотя для 32 Кб кэша 4 потока по 1000 чисел - это 32000 + ещё немного на всякие переменные и другие приложения, возможно, и хватит, но я бы сделал поменьше, тем более, можем попасться 8-ядерник с 32 Кб кэшем... по 200-400 нормально), то в кэш загрузятся сначала первые 1000 чисел (и при многократном использовании эти 1000 чисел будут читаться из массива гораздо быстрее, чем при хаотичном обращении ко всему массиву... под хаотичном я подразумеваю и последовательное), затем следующие 1000. И работа будет идти быстрее. По-другому ещё объясню. Если прочитать большой массив последовательно 1000 раз подряд, это будет медленнее, чем прочитать каждое число 1000 раз подряд, а потом переходить к следующему числу. Ну или читать порциями: сначала 1000 чисел 1000 раз подряд, затем следующие 1000 чисел 1000 раз подряд. Это будет быстрее, чем читать весь массив последовательно 1000 раз подряд ![]() По алгоритмам можно кинуть тему в Алгоритмы, например... Но самый большой прирост скорости будет от перехода на 64 бита (если сейчас прога работает на 32-х). Ну и от перехода с конфигурации Debug на Release (если вдруг...). Остальное существенного прироста не даст.
1
|
||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 25.04.2017, 13:19 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Решил глянуть файл ассемблерного кода, который компилятор студии сделал.
25 тыс. строк (с машинным кодом - 35 тыс.строк). Не профессионалу (как мне) полжизни разгребать. Какие-то куски опознаю, какие-то нет. unsigned long long - это и есть int64 без знаковый, что бы больший диапазон влез. Понятное дело Release, оптимизация в С++ компиляторе - максимальная.На данном алгоритме максимальная граница диапазона (2^64)^(1/3)-1 = 2 642 245 Посчитал, получил - 93 решения. Кликните здесь для просмотра всего текста
Размер массива/вектора - 2 642 245 элементов. Количество итераций - 346 331 120 300 Время выполнения 15,9 мин. ПК: Кликните здесь для просмотра всего текста
Тип ЦП QuadCore Intel Core i7-3770, 3700 MHz (37 x 100) Системная память 8156 МБ (DDR3-1333 DDR3 SDRAM) Добавлено через 1 час 34 минуты 8 логических ядер - 8 потоков.
0
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||
| 25.04.2017, 16:12 [ТС] | ||
![]() ![]() Так же хотел запилить вычисления числа "Пи", до миллионного знака, но .exe весить стал неприлично много. Не по теме: Из студента я давно вырос, эх... были времена (и учился по совершенно другому направлению), собственно по тому направлению и работаю, посему программирую редко. А задачка эта на форуме приглянулась, решил решить :) Поэтому можно в массив и не класть, хотя можно развлечь народ быстротой вычисления (до первого декомпиллирования, хотя в 30 тыс. строк найти сей массив - постараться нужно будет) Добавлено через 11 минут Можно конечно и дальше считать, но тогда нужно подключать длинную арифметику. Есть и библиотеки mpir, но это сразу снизит скорость вычисления, да и никто не оценит.
0
|
||
|
Asm/C++/Delphi/Py/PHP/VBA
|
||
| 25.04.2017, 18:09 | ||
|
Дальше замучаешься ждать просто...
![]() ![]() А вообще, млн знаков можно в ≈400 Кб (с небольшим) запросто засунуть. Если каждые 3 цифры запихивать в 10 бит (число от 0 до 1023) или 12 цифр в 40 бит (равно 5 байт). Будет сжатие даже лучше, чем у 7z и rar5 ![]() Добавлено через 27 минут У меня есть число Пи до 1 млрд знаков после запятой, числа Фи и e с точностью до 500 млн+1 знаков (вычислено с помощью Wolfram Mathematica 9.0). Если что, обращайтесь!
0
|
||
|
1719 / 568 / 187
Регистрация: 12.03.2016
Сообщений: 2,169
|
||
| 25.04.2017, 18:23 | ||
0
|
||
|
|
|
| 25.04.2017, 19:42 [ТС] | |
|
мановар, Jin X, к сожалению так:
19 октября 2011 года Александр Йи и Сигэру Кондо рассчитали последовательность с точностью в 10 триллионов цифр после запятой персональном ПК! см.здесь Кликните здесь для просмотра всего текста
НА персональном ПК - два шестиядерных процессора Intel Xeon X5680 (3,33 ГГц). Также были установлены 96 гигабайт оперативной памяти и 30 жестких дисков общим объемом 59 терабайт. Для нового рекорда пришлось добавить 10 жестких дисков.
Оригинал новости находится в интернет-журнале «iScience» (iScience.ru): http://iscience.ru/2011/10/20/... ya-%CF%80/ Не по теме: Голландский математик Брауэр в первой половине XX века привёл в качестве примера бессмысленной задачи поиск в десятичном разложении ПИ последовательности 0123456789 — по его мнению, нужная для этого точность никогда не будет достигнута. В конце XX века эта последовательность была обнаружена, она начинается с 17 387 594 880-го знака после запятой. Википедия
1
|
|
|
1719 / 568 / 187
Регистрация: 12.03.2016
Сообщений: 2,169
|
|
| 25.04.2017, 19:46 | |
|
0
|
|
|
|
|
| 25.04.2017, 20:24 [ТС] | |
|
А так же купить кондей и готовится к счетам за свет ))
0
|
|
| 25.04.2017, 20:24 | |
|
Помогаю со студенческими работами здесь
20
Ассемблерная вставка, нужен код зажатого shift-а help; вставка на ассемблере в код паскаля Перевести ассемблерный код TASM в программный код для архитектуры ARM Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога
Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
|
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование
. \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json>
Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом.
# Check if. . .
|
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так:
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347
Основана на STM32F303RBT6.
На борту пять. . .
|
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
|
|
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу,
и светлой Луне.
В мире
покоя нет
и люди
не могут жить в тишине.
А жить им немного лет.
|
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила»
«Время-Деньги»
«Деньги -Пуля»
|
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога
Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
|
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога
Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
|