![]() |
|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
![]() |
|
|
Опции темы | Поиск в этой теме |
![]() |
#12 |
C/C++, Asm
Участник клуба
Регистрация: 02.03.2010
Сообщений: 1,323
|
![]()
пример 2: AMD cpuid
Так случилось, по непонятным причинам, что то что может Intel cpu всегда, AMD cpu может только иногда. Поэтому, и не только поэтому, бывает полезно знать на что способен cpu. Данный пример только для AMD cpu, даже если этот код сработает на Intel, его резутат не будет иметь смысла, поскольку AMD CPUID и Intel CPUID практически не имеют ничего общего. Кому интересно может обратиться к первоисточникам, которые можно найти здесь и здесь. |
![]() |
![]() |
![]() |
#13 | |||
Старожил
Регистрация: 02.01.2011
Сообщений: 3,328
|
![]()
Вызов функции dll из программы на C.
Описание: при нажатии на кнопку вызывается функция Add, которая находится в dll. Add принимает два числа и возращает их сумму. ![]() Код:
Код:
Код:
Цитата:
Цитата:
Цитата:
Последний раз редактировалось 8Observer8; 04.11.2012 в 23:25. |
|||
![]() |
![]() |
![]() |
#14 |
Старожил
Регистрация: 02.01.2011
Сообщений: 3,328
|
![]()
Открываем и закрываем CD-ROM
Код:
|
![]() |
![]() |
![]() |
#15 |
C/C++, Asm
Участник клуба
Регистрация: 02.03.2010
Сообщений: 1,323
|
![]()
Про повышение производительности кода.
Ходят слухи буд-то код написанный на ассемблере по определению будет быстрее чем код полученый от компилятора языка более высокого уровня. Возможно это было правдой в прошлом веке, сегодня это не так, далеко не так. Для того чтобы сделать на пол-такта быстрее чем хороший компилятор прихотся потрахаться, недетски. Единственный надежный способ сделать быстрее это кодить под конкретную архитектуру (legacy x86, Pentium, Core, Sandy Bridge), зная сколько и чего (ресурсов) доступно. Если нет уверенности на какой архитектуре будет использоваться код, то писание на ассемблере не увиличивает ничего кроме геммороя. Если все-таки сильно хочется сделать побыстрее, то как ни странно самый простой и наиболее эффективный способ повышения производительности кода называется раскрытие циклов (loop unrolling). Это значит, что если например есть цикл с фиксированным числом повторений Код:
Код:
Еще периодически слышу, что LOOP работает быстрее чем SUB rcx & JMP. Так случилось, что ни с чем младше Core работать не приходилось, и по имеющемуся опыту LOOP в среднем в два раза медленнее чем SUB rcx & JMP. Плюс у LOOP _цель есть ограничение в 128 байт на максимальное расстояние до _цели. Есть еще общее правило оптимизации производительности, которое гласит, что все цели переходов (jump targets) полезно выравнивать по 16 байтной границе. Сильного эффекта от последнего наблюдать не приходилось, но и хуже от него не становится, так что можно использовать. Последний раз редактировалось f.hump; 18.11.2012 в 01:31. |
![]() |
![]() |
![]() |
#16 |
C/C++, Asm
Участник клуба
Регистрация: 02.03.2010
Сообщений: 1,323
|
![]()
Продолжая тему повышения производительности, напомню очевидные вещи.
Чтение из памяти быстрее записи в память. Поэтому константы, или относительно редко меняющиеся параметры выгодно держать в памяти, а часто меняющиеся на регистрах. Последовательный доступ к памяти быстрее случайного, по той причине, что процессор умеет обнуруживать последовательный доступ и кешировать зараннее то что может потребоваться в недалеком будущем, при случайном доступе он тоже кеширует, но не совсем то. Кеширует процессор кеш-линиями шириной 32 или 64 байта (зависит от архитектуры). И тут полезно, чтобы размер данных/параметров был кратен ширине кеш-линии , либо целое число параметров заполняло линию целиком (не было разрывов кеш-линии). Наиболее известный пример такой оптимизации это фактический отказ от 10-байтного формата данных с плавающей точкой, который поддерживается х87 FPU. Если четыре 8-ми байтных с плавающей точкой покрывают 32-х байтную линию без остатка, для доступа к четвертому 10-ти байтному с плавающей точкой потребуется заполнение второй линии и дополнительное выравнивание, что фактически убивает производительность. Последний раз редактировалось f.hump; 18.11.2012 в 01:30. |
![]() |
![]() |
![]() |
#17 |
C/C++, Asm
Участник клуба
Регистрация: 02.03.2010
Сообщений: 1,323
|
![]()
С появлением потоковых расширений (streaming extensions) на x86, появилсь возможность поднять производительность кода, который можно распараллелить. Должен отметтить, что коду, в котором нечего распараллеливать, наличие потоковых расшерений абсолютно параллельно. По имеющемуся опыту вычислительные задачи действительно имеют хороший потенциал для распаллеливания и серезно выигрывают при использовании потоковых расширений. Тут, я думаю, место для простого примера. Однажды столнулся с конвертацией массива целых из big-endian в little-endian и обратно. С одной стороны это можно сделать так:
Код:
Код:
Код:
|
![]() |
![]() |
![]() |
#18 |
C/C++, Asm
Участник клуба
Регистрация: 02.03.2010
Сообщений: 1,323
|
![]()
В общем и в целом потоковые расширения (SSE, AVX) очень и очень полезная вещь: 16 регистров (xmm) шириной 16 байт (SSE), или 16 регистров (ymm) шириной 32 байта (AVX) + целочиcленная арифметика/арифметика с плавающей точкой/перестановки на этих регистрах. (про MMX я не пишу, потому что это прошлый век).
При использовании потоковых расширений выравнивание памяти - необходимость. Все операции с операндом указывающим на память (за исключением MOVxxx) требуют, чтобы память, на которую указывает операнд была выравнена по 16-ти байтной границе, иначе general protection exception. Должен признать, что когда речь идет о целочисленной арифметике, старая добрая legacy x86 очень даже ничего, в том смысле, что если сделать полный unroll код оказывается всего в 1.5-2 раза медленне кода с использованием потоковых расширений (хотя может это я где-то слажал). Правильное использование потоковых расширений на флоатах теоретически ускоряет выполнение задачи в 4 раза. Простой пример по этой теме линейный метод наименьших квадратов. С одной стороны его можно записать так: Код:
Последний раз редактировалось f.hump; 25.11.2012 в 23:27. |
![]() |
![]() |
![]() |
#19 |
C/C++, Asm
Участник клуба
Регистрация: 02.03.2010
Сообщений: 1,323
|
![]()
с другой стороны так:
Код:
Последний раз редактировалось f.hump; 25.11.2012 в 23:36. |
![]() |
![]() |
![]() |
#20 |
C/C++, Asm
Участник клуба
Регистрация: 02.03.2010
Сообщений: 1,323
|
![]()
Еще пару слов про потоковые расширения. Не смотря на то что SSE/AVX иструкции стоят в одной очереди с x86 иструкциями, выполняются они на независимых исполнительных блоках. Это значит, что код для x86 может выполнятся одновременно с логически слабо зависимым/независимым кодом для SSE/AVX, тем самым повышая производительность. Конечно, процессор сканирует очедь с целью обнаружения таких ситуаций, учитывая что глубина сканирования конечна, имеет смысл упростить задачу процессора чередуя код для x86 и SSE/AVX.
Код:
Последний раз редактировалось f.hump; 27.11.2012 в 23:03. |
![]() |
![]() |
![]() |
|
![]() |
||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Составить на языке ассемблера IBM PC подпрорамму вычисления | Airat1790 | Помощь студентам | 0 | 18.04.2012 13:39 |
Нужны шаблоны(примеры программ) по Паскалю | Сержuk | Помощь студентам | 1 | 10.03.2011 14:48 |
На языке ассемблера IBM PC создать подпрограммы: | Gertryda | Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM | 1 | 09.01.2011 23:13 |