aaarrr 69 17 октября, 2005 Опубликовано 17 октября, 2005 · Жалоба Опять слишком "жесткое" утверждение. Поймите и Вы, я тоже не цепляюсь именно к этому примеру. Но Ваши категоричные утверждения Вы хоть знаете где Ваш компилятор (именно тот с которым Вы работаете) делает оптимизацию (и какие приемы лучше при этом использовать). Ну хотя бы такую классику ++j или j++. Или сравниваете C-программы и Asm-прог только по конечному результату? Извините, если Вам показалось какое-то упорство с моей стороны (навеянное впрочем личным опытом, пусть и несколько уставревшим, и знания некоторых основ компилирования). Но ведь весь разговор в течении последнего часа - и поэтому выбранный тон - для лучшего взаимопонимания От своей реплики с условиями задачи не отказываюсь <{POST_SNAPBACK}> Поверьте, я прекрасно знаю, где и как работает оптимизация у моего компилятора. Когда-то угробил прилично времени на действия типа: модифицируем код->компилируем->дизассемблируем->смотрим, где накосячено. А приведенная мной задача не решается на Ц оптимально. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Виктория 0 17 октября, 2005 Опубликовано 17 октября, 2005 · Жалоба Прерываюсь на какое-то время. Пора домой Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dot 0 17 октября, 2005 Опубликовано 17 октября, 2005 · Жалоба Ничего себе -- " ARM начинающим"! Я вот какой аспект хочу поднять: ну вот отладили вы программу на С, добились (может быть с трудом) того, что она успевает реагировать на какие-то внешние воздействия. Поменяли компилятор (апгрейд версии, заказчик вдруг решил перейти на другой, либо проект открытый) -- девайс не работает, нужно искать то "критическое место" , которое портит все из-за изменившегося времени выполнения. Если заранее найти такие места и написать их на асме, то код станет гораздо "сопровождаемее". Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 17 октября, 2005 Опубликовано 17 октября, 2005 · Жалоба Поменяли компилятор (апгрейд версии, заказчик вдруг решил перейти на другой, либо проект открытый) -- девайс не работает, нужно искать то "критическое место" , которое портит все из-за изменившегося времени выполнения. <{POST_SNAPBACK}> Как правило, при смене компилятора вылезает множество "критических мест", а грабли случаются не из-за изменившегося времени выполнения, а по иным, ведомым только шайтану, причинам. Заранее соломку постелить не получится. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NickS 0 17 октября, 2005 Опубликовано 17 октября, 2005 · Жалоба Какая разница, сколько там флэш. Эмпирическая оценка разбухания кода Си по сравнениею с асм 1,3-1,5 раз. Быстродействия примерно столько же. Кочечно, есть и частные случаи. Внесу и я свое замечание на 5 копеек. Вообще-то как я замечал оценка разбухания кода и соответственно быстродействие оличается в 3-4 раза. Это, мягко говоря, неправда. Только сравнивать надо не отдельные функции, а модуль целиком, содержащий большое количество функций. <{POST_SNAPBACK}> При увеличении количества функций все лишь нивелируется, стремясь к среднему значению. Если можно еще найти отдельные локальные места, где на асм можно выиграть 3-4 раза объема или быстродействия по сравнению с Ц, то в большом проекте эти места утонут в море среднестатистических показателей. <{POST_SNAPBACK}> Судя по всему вы не писали достаточно большие проекты на ASM. У меня, конечно, довольно редко воникает проект продублированный на С и ASM. Однако, например для кодека G.723.1 переписывание только базовых функций на ASM привело к уменьшению времени обработки одного фрейма с 200мс до 25, что соответствует примерно 10 кратному ускорению времени выполнения. Для обработчика обмена по USB выигрышь по скорости обработки выросло в 4 раза. И как раз чем бльше проект, тем заметнее разница. Если на отдельных простых функциях разница составляет 30% то на сложных функциях, а уж тем более больших проектах разница достигает 3-4 каратного превосходства. И чтобы не быть совсем голословным: Вы предлагали сравнить на реальном проекте. У меня недавно был проект часть которого также была выполненый на С и ASM. Это real FFT. На котором также легко демонстрируется трехкратное превосходство ASM над С. Итак: Есть входной масив данных int16 Data[2048]; Так же есть входной оконный масив int16 WIN[2048]; Наебходимо выполнить следующее: Первоначально поэлементно умножить елемент данных на елемент окна Data=Data*WIN/65536; Далее выполнить реальное преобразование фурье по 2048 точкам. И получить квадкат абсолютного значения по получившимся комплексным отсчетам. ABS= RE*RE+Im*Im; Выходной массив это int32 Abs[1024] расположен на месте входного массива данных Data[2048]. пример на ASM прилагаю: Он занимает 4К памяти данных, и во Flash 4К под окно, 4К под служебные таблицы и совсем чуть-чуть под программы. Один цикл вычислений занимает примерно 500 000 цикло для 7TDMI. На С аналогичная программ требовала примерно в 3 раза больше. Если вы полагаете, что сможете получить аналогичные ( в приделах 30% ) результаты на С, покажите это. В принципе дело достаточное простое для С. Умножение на окно и авсолютное значение - функции достаточно простые. А real FFT предлагается в довольно большом количестве библиотек если лень писать самому. fft_sample.zip Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andy_Mozzhevilov 0 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Тогда еще раз условия задачи: процессор - ?, размер элемента массива - байт? и т.п. <{POST_SNAPBACK}> Хорошо. Условия задачи: 1. Процессор: ARM7 2. Размер элемента массива: 4 байта (слово) 3. Количество элементов: 2048 4. Источник и приемник выравнены по границе слова (ложка дёгтя здесь отсутствует, но можно добавить - 4 байта из 8192 картину не испортят) 5. Оптимизация на скорость Попробуйте решить это на Ц и сравните с АСМ <{POST_SNAPBACK}> Опубликуйте асм-код Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andy_Mozzhevilov 0 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Ничего себе -- " ARM начинающим"! так чтобы жизнь медом не казалась :) Я вот какой аспект хочу поднять: ну вот отладили вы программу на С, добились (может быть с трудом) того, что она успевает реагировать на какие-то внешние воздействия. При правильном выборе процессора как правило все успевает. А то иногда встречаются люди, которые mp3 хотят программно делать на х51. Или USB или Ethernet генерить программно. Поменяли компилятор (апгрейд версии, апдейты версии компилятора не приводят к худшим результатам, как правило. Конечно бывают случаи, когда в компиляторы добавляются баги, противно конечно, но находится. заказчик вдруг решил перейти на другой, Заказчику глубоко фиолетово на каком компиляторе решена его проблема. Он, возможно даже не знает слова компилятор. либо проект открытый) -- девайс не работает, нужно искать то "критическое место" , которое портит все из-за изменившегося времени выполнения. Никто не пишет программы в притык к 100% производительности процессора, если это так, то тут ошибка в ДНК. Если заранее найти такие места и написать их на асме, то код станет гораздо "сопровождаемее". <{POST_SNAPBACK}> какие места? как определить, что вот это место такое, а вот это место - не такое? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andy_Mozzhevilov 0 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Судя по всему вы не писали достаточно большие проекты на ASM. У меня, конечно, довольно редко воникает проект продублированный на С и ASM. Однако, например для кодека G.723.1 переписывание только базовых функций на ASM привело к уменьшению времени обработки одного фрейма с 200мс до 25, что соответствует примерно 10 кратному ускорению времени выполнения. Для обработчика обмена по USB выигрышь по скорости обработки выросло в 4 раза. Я не работаю в этих областях, и к сожалению не могу прокомментировать данные цифры. Но 200 мс и 25 вообще выглядит весьма странно. Умножение на окно и авсолютное значение - функции достаточно простые. Да, простые, поэтому и писание их заняло не более получаса, с учетом настройки опций этого тестового проекта и приведения ваших исходников к синтаксису IAR. Итак, IAR 4.30: Функция window, ваш вариант: ; GLOBAL window PUBLIC window window stmfd r13!,{r2-r3,r14} ldr r14,=WINTABLE mov r1,r1,lsl #1 win_l0 ldrsh r2,[r14],#2;WIN[i] ldrsh r3,[r0] ;Buf[i] mul r3,r2,r3 mov r3,r3,asr #15 strh r3,[r0],#2;Buf[i] subs r1,r1,#1 bgt win_l0 ldmfd r13!,{r2-r3,pc} Функция window, мой вариант: static const signed short Rfft_c_wintbl[2048] = {...} void window_c (signed short *Buf, int Len) { const signed short *win = Rfft_c_wintbl; do { *Buf = (*Buf * *win) /65536; Buf++; win++; } while (--Len); } 143 void window_c (signed short *Buf, int Len) 144 { 145 const signed short *win = Rfft_c_wintbl; \ window_c: \ 00000000 24209FE5 LDR R2,??window_c_0 ;; ??Rfft_c_wintbl 146 147 do 148 { 149 *Buf = (*Buf * *win) /65536; \ ??window_c_1: \ 00000004 F030D0E1 LDRSH R3,[R0, #+0] \ 00000008 ........ LDRSH R12,[R2], #+0x2 \ 0000000C 9C0303E0 MUL R3,R12,R3 \ 00000010 C3C7A0E1 MOV R12,R3, ASR #+0xF \ 00000014 2C3883E0 ADD R3,R3,R12, LSR #+0x10 \ 00000018 4338A0E1 MOV R3,R3, ASR #+0x10 \ 0000001C ........ STRH R3,[R0], #+0x2 150 Buf++; 151 win++; 152 } while (--Len); \ 00000020 011051E2 SUBS R1,R1,#+0x1 \ 00000024 F6FFFF1A BNE ??window_c_1 153 } \ 00000028 0EF0A0E1 MOV PC,LR ;; return \ ??window_c_0: \ 0000002C ........ DC32 ??Rfft_c_wintbl Все тело цикла практически одинаково, за исключением деления на 65536, что в вашем варианте выглядит просто как арифметический сдвиг mov r3,r3,asr #15 а в варианте компилятора, как \ 00000010 C3C7A0E1 MOV R12,R3, ASR #+0xF \ 00000014 2C3883E0 ADD R3,R3,R12, LSR #+0x10 \ 00000018 4338A0E1 MOV R3,R3, ASR #+0x10 Что по сути правильно, поскольку в вашем варианте при делении отрицательного числа никогда не будет получен 0, максимум -1. В общем, округление результата будет несколько не туда и в разные стороны для положительных и отрицательных чисел. Возможно, в вашем приложении это качественно и не сказывается на окончательный результат, но тем не менее, в ТЗ было прописано деление. Далее, функция abs, ваша abs_l0 ldrsh r2,[r0];Buf[i] mul r3,r2,r2 ldrsh r2,[r0,#2];Buf[i] mla r3,r2,r2,r3 mov r3,r3,asr #14 str r3,[r0],#4;Buf[i] subs r1,r1,#1 bgt abs_l0 моя void absr_c (short *Buf, int Len) { unsigned int *p_out = (unsigned int *)Buf; do { int temp = *Buf * *Buf; Buf++; temp += *Buf * *Buf; Buf++; *p_out++ = temp; } while (--Len); } 155 void absr_c (short *Buf, int Len) 156 { 157 unsigned int *p_out = (unsigned int *)Buf; \ absr_c: \ 00000000 0020A0E1 MOV R2,R0 158 159 do 160 { 161 int temp = *Buf * *Buf; \ ??absr_c_0: \ 00000004 F030D0E1 LDRSH R3,[R0, #+0] \ 00000008 93030CE0 MUL R12,R3,R3 162 Buf++; 163 temp += *Buf * *Buf; \ 0000000C F230F0E1 LDRSH R3,[R0, #+0x2]! \ 00000010 93C32CE0 MLA R12,R3,R3,R12 164 Buf++; \ 00000014 020080E2 ADD R0,R0,#+0x2 165 *p_out++ = temp; \ 00000018 ........ STR R12,[R2], #+0x4 166 } while (--Len); \ 0000001C 011051E2 SUBS R1,R1,#+0x1 \ 00000020 F7FFFF1A BNE ??absr_c_0 167 } \ 00000024 0EF0A0E1 MOV PC,LR ;; return То есть издержки Ц - дополнительная команда ADD R0,R0,#+0x2. Кроме того, у вас там есть масштабирование результата mov r3,r3,asr #14 хотя по ТЗ это описано не было. При добавлении масштабирования код для этой операции создается такой же, как и в верхнем примере. А real FFT предлагается в довольно большом количестве библиотек если лень писать самому. <{POST_SNAPBACK}> Это уже не так быстро, а поскольку я это делаю в рабочее время, то я возьму таймаут для написание этих функци и попробую протестировать на реальном железе. Впрочем, скоро не обещаю. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Вроде как подобные споры - дела давно прошедших дней. Если есть в программе "критичные" места, скорость выполнения которых сильно влияет на работу всей программы, то есть смысл их переписать на ассемблере. Ну и совершенно согласен с коллегами, что надо сначала выбрать процессор, которому данная задача по "зубам", благо сейчас есть из чего выбрать. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NickS 0 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Я и не ожидал большого эфекта от функций вычисления абсолютного значения или умпожения на окно. Как я уже говорил эти функции слишком простые, что бы не быть однозначными. В них особо не на портачишь. Давайте обождем самого вычисления Фурье и сравним итог. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Я и не ожидал большого эфекта от функций вычисления абсолютного значения или умпожения на окно. Как я уже говорил эти функции слишком простые, что бы не быть однозначными. В них особо не на портачишь. Давайте обождем самого вычисления Фурье и сравним итог. <{POST_SNAPBACK}> Зато эти функции - типовые для задач, решаемых на МК. В отличие от FFT, которая есть уже весьма специальная задача, кои часто решают на более специальных процессорах, нежели АРМ. И в типовом проекте на МК удельный вес функций типа FFT исчезающе мал. Есть подозрение, что большинству пользователей АРМ (да и других МК) не приходится с этим иметь дело. И если уж этот специальный случай не оправдал у Вас себя на С, то, как же сказали, его можно и на асме реализовать. Но это не повод и не причина писать на асме все. А эффективность кодогенерации С компилятора, ихмо, была продемонстрирована с блеском. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NickS 0 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Я и не ожидал большого эфекта от функций вычисления абсолютного значения или умпожения на окно. Как я уже говорил эти функции слишком простые, что бы не быть однозначными. В них особо не на портачишь. Давайте обождем самого вычисления Фурье и сравним итог. <{POST_SNAPBACK}> Зато эти функции - типовые для задач, решаемых на МК. В отличие от FFT, которая есть уже весьма специальная задача, кои часто решают на более специальных процессорах, нежели АРМ. И в типовом проекте на МК удельный вес функций типа FFT исчезающе мал. Есть подозрение, что большинству пользователей АРМ (да и других МК) не приходится с этим иметь дело. И если уж этот специальный случай не оправдал у Вас себя на С, то, как же сказали, его можно и на асме реализовать. Но это не повод и не причина писать на асме все. А эффективность кодогенерации С компилятора, ихмо, была продемонстрирована с блеском. <{POST_SNAPBACK}> Эти функции как раз не типовые. Большинство функций которые я применяю значительно сложнее. От вывода на экран и обработки кнопок до алгоритма работы. Это очень простые функции занимающие несколько строк в исходном тексте. В большинстве своем функции нанимают в среднем около сотни строк. В качестве примера достаточно сложной функции и используется FFT. Для меня это пример который у меня реализован и на С и на ASM и разницу здесь я знаю. А на любой достаточно сложной функции разница станет существенной. А поскольку тестами утруждаться никто не хочет и делает проверку на примитивных функциях и возникает легенда об высокой эффективности С. Хотя это не так. Можете посмотреть сами взяв функцию или модуль хотя бы в несколько сотен строк. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andy_Mozzhevilov 0 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Эти функции как раз не типовые. Большинство функций которые я применяю значительно сложнее. От вывода на экран и обработки кнопок до алгоритма работы. Это очень простые функции занимающие несколько строк в исходном тексте. Каждая функция в конечном итоге состоит из каких-то элементарных действий. Если на элементарные действия Ц дает оверхед на 30% (к примеру), то с чего вдруг вы считаете, что при увеличении количества этих действий вдруг произойдет рост неэффективности Ц в геометрической прогресии? В большинстве своем функции нанимают в среднем около сотни строк. В качестве примера достаточно сложной функции и используется FFT. Для меня это пример который у меня реализован и на С и на ASM и разницу здесь я знаю. Так приведите пример на Ц, я его хотя бы откомпилирую, чтобы не писать самому. Хотя бы посмотреть, откуда там у оверхеда ноги растут. А на любой достаточно сложной функции разница станет существенной. Если вы имеете большой опыт сравнения, то скажите за счет чего? А поскольку тестами утруждаться никто не хочет и делает проверку на примитивных функциях и возникает легенда об высокой эффективности С. Хотя это не так. Можете посмотреть сами взяв функцию или модуль хотя бы в несколько сотен строк. <{POST_SNAPBACK}> Брали, смотрели листинг после компилятора. Да, где-то можно сделать чуть эффективнее, но как правило не намного. А некоторые виды оптимизации, которые выполняет компилятор - руками делать на ассемблере, свихнуться можно. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба Опубликуйте асм-код <{POST_SNAPBACK}> Пожалуйста: copy0 stmfd sp!, {r4-r9, r14} mov r2, #0x80 copy0_0 ldmia r0!, {r3-r9, r12} stmia r1!, {r3-r9, r12} ldmia r0!, {r3-r9, r12} stmia r1!, {r3-r9, r12} ldmia r0!, {r3-r9, r12} stmia r1!, {r3-r9, r12} ldmia r0!, {r3-r9, r12} stmia r1!, {r3-r9, r12} subs r2, r2, #0x01 bne copy0_0 ldmfd sp!, {r4-r9, pc} Должен признать, что разные компилеры ведут себя в такой ситуации по-разному: некоторые маразматично, а некоторые вполне ничего. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Виктория 0 18 октября, 2005 Опубликовано 18 октября, 2005 · Жалоба To aaarrr Весь день I-neta не было :( (и IARa в том числе). Поэтому пример на подвернувшемся GNU-шном Си (из тех, что вполне ничего). В общем то это только идея, которую можно и дальше продвинуть (соопитимизировать). Кстати, у Andy Mozzhevilov тоже можно дальше сооптимизировать, если уж это так необходимо. Итак множественная загрузка: struct m8 { unsigned long w[8]; }; struct m8 a[128]; struct m8 b[128]; void copy0(register struct m8 *pa, register struct m8 *pb) {register int i; for(i=128; i!=0; --i) *pb++=*pa++; } void main() { copy0(a,B); } и полностью выход на асме (чтоб без обмана) .file "prim.c" .text .align 2 .global copy0 .type copy0, %function copy0: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 stmfd sp!, {r4, r5, r6, lr} mov r5, r0 mov r4, r1 mov r6, #128 .L6: mov lr, r4 mov ip, r5 ldmia ip!, {r0, r1, r2, r3} stmia lr!, {r0, r1, r2, r3} ldmia ip, {r0, r1, r2, r3} stmia lr, {r0, r1, r2, r3} add r5, r5, #32 add r4, r4, #32 subs r6, r6, #1 ldmeqfd sp!, {r4, r5, r6, pc} b .L6 .size copy0, .-copy0 .align 2 .global main .type main, %function main: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 1, uses_anonymous_args = 0 mov ip, sp stmfd sp!, {fp, ip, lr, pc} sub fp, ip, #4 ldr r0, .L10 ldr r1, .L10+4 bl copy0 ldmea fp, {fp, sp, pc} .L11: .align 2 .L10: .word a .word b .size main, .-main .comm a, 4096, 32 .comm b, 4096, 32 .ident "GCC: (GNU) 3.3.1" командная строка компилятора arm-uclibc-gcc.exe -S -mcpu=arm7tdmi -O -o oops.s prim.c Прощаюсь до завтра Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться