Алексей
Где кошачья мята?!
offline
Опыт:
26,543Активность: |
Ещё раз повторю, что создание эффективного кода, по быстродействию не уступающего ассемблерному, возможно и на ЯВУ (том же Си). Просто нужно учитывать архитектурные особенности процессоров и памяти. Вот ещё один пример:
Код:
Если переменные типа char занимают в памяти 1 байт, byte – тоже байт, а integer и single – по 4 байта, то сколько памяти займёт весь массив? Считаем: (1+4+1+4)*1000=10000 байт. Так? А вот и нет! На самом деле такой массив займёт 16000 байт! А вот если объявить так: Код:
Код:
Код:
|
10.04.2006, 15:21 | #21
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
NETRAT
offline
Опыт:
83,762Активность: |
Может быть это связяно с выходом числа 4096*4 за границы некоторого сегмента?
Вообще код, конечно извратный, не думаю что я стал бы так что-нить писать, находясь в здравом уме - ибо его читать неприятно Как оно будет выглядеть в асме... Цикл a в регистр a-g Проверка флагов a1 в регистр 4096 в индексный регистр a1+индексный регистр a1 в память a2 в регистр 8192 в индексный регистр a2+индексный регистр a2 в память a3 в регистр 12288 в индексный регистр a3+индексный регистр a3 в память a4 в регистр 16384 в индексный регистр a4+индексный регистр a4 в память a5 в регистр 20480 в индексный регистр a5+индексный регистр a5 в память inc a джамп Ну фиг его знает, неявно это, мб потому что сегменты памяти по размеру меньше 16K и если читать в одном цикле из разных сегментов, то работать будет намного медленнее чем если читать двумя циклами, каждый для своего сегмента. Я вот что подумал - ты же тут сам подсказку дал, вероятно, память выделяется сегментами кратными степени двойки(а может 4 или больше), то есть теоретически понятно почему по записи выделяется больше места чем им положено - ибо меньше просто нельзя - на размещение этих записей не хватит места. Так вот, под целостные сегменты, коими у нас и являются массивы, выделяется непрерывный сегмент памяти(ибо адресация прямая). То есть очевидно что массив записей не может занимать меньше места чем набор массивов для каждого из полей записи. Примерно так и обуславливается скорость работы - это время на перемещение индекса между сегментами памяти. Похоже на правду. Если это конечно так, то, вроде бы отношение скоростей должно изменяться в зависимости от числа g NETRAT добавил: Интересно что чем круче компьютеры, тем меньше внимания уделяется скорости и оптимальности работы - то есть и так "проглотит", иногда лучше написать хоть как-то, а потом оптимизировать. То есть на первый план выходит high-level, ибо мощности позволяют наворотить удобные среды, которые могут сами себя контроллировать за счет потери быстродействия. Тенденция, однако... NETRAT добавил: Да, то что память выделяется сегментами с размером, кратным степени двойки - это очевидно, по другому просто и быть не может - ибо адресация памяти была бы невозможна(или затруднена или неоптимальна), думаю, что это все обьясняет NETRAT добавил: Я о том, что как ни крути, однако код на асме можно лучше оптимизировать. Кстати, помницца, я еще на втором курсе научился использовать ассемблерные вставки в Дельфе и в С... |
11.04.2006, 03:35 | #22
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
Алексей
Где кошачья мята?!
offline
Опыт:
26,543Активность: |
Да, память действительно выделяется блоками, размер которых кратен степени 2. Хотя на asm можно выделять блок произвольного размера. Тут причина ещё в выравнивании: доступ к данным, выровненным на величину, кратную их размеру, осуществляется быстрее.
Поэтому все современные компиляторы выравнивают данные. Переменные, занимающие 1 байт, могут располагаться по любому адресу. 2-байтовые переменные располагаются только по чётным адресам. 4-байтовые - по адресам, делящимся на 4. За счёт перерасхода памяти достигается значительное увеличение быстродействия. Поэтому объявление вида: a:byte; b:integer; b:byte; займёт в памяти не (4+2), а (4+4+1), т.к. между a и b компилятор оставит 3 пустых байта - для выравнивания. А вот если объявить b:integer; a,b:byte; то всё "уляжется" вплотную. Впрочем, всё сказанное относится только к глобальным переменным. Локальные переменные - разговор особый (там всё куда сложнее). . Вообще, чтение данных из оперативной памяти осуществляется ОЧЕНЬ медленно. Если тактовые частоты процессоров уже давно перевалили за 3000МГц, то памяти - всего 200МГц. Вот как осуществляется чтение данных из памяти (растактовка из документации):
Современные процессоры пользуются четырёхассоциативным кэшем. И вышеуказанный цикл построен так, что "заваливает" кэш мусором и процессору всё время приходится ждать, пока данные считаются из оперативки. Отсюда - 6-кратное падение производительности (кэш не может хранить более 4 ячеек с одинаковыми "установочными" адресами – т.е. адресами, отличающимися на n*4096). Код на ASM действительно великолепно поддаётся оптимизации, но это уже требует глубокого знания архитектуры процессора. |
11.04.2006, 10:48 | #23
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
NETRAT
offline
Опыт:
83,762Активность: |
Да, вот как раз триггерами мы сейчас и занимаемся... Булева временная логика...
Такие сложности в основном делаются для повышения надежности "механизма", ибо если отдельно рассматривать элементы такой схемы, то становится понятно почему без дополнительных проверок не обойтись - ибо есть вероятность сбоя, потери данных, ошибки, а в ядре это должно быть исключено - чревато NETRAT добавил: Именно поэтому хай-левел работает без глюков... |
11.04.2006, 14:10 | #24
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|