|
многоканальная обработка, нюансы |
|
|
|
Dec 6 2006, 17:21
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Doka @ Dec 6 2006, 12:53)  в ЦОС при переходе от одноканальных алгоритмов обработки даннных к многоканальным часто приходится иметь дело с контекстом канала - наиболее распространенный способ для этого - завести структуру, содержащий контекст обработки канала. и в программе использовать массив структур размерностью с число каналов.
Однако вызываться они могут по разному: 1. вызываемой процедуре передается номер канала (фактически - индекс массива структур) 2. вызываемой процедуре передается адрес указателя на структуру
интересен выбор оптимального способа в приложении использования на сигнальниках (архитектура TI C5000) 2й способ , как я понимаю позволяет не привязываться к массиву структур - это позволяет (при большом объеме контекста) размещать структуры в карте памяти с разрывом (если поиному не влазят) либо в разные секции памяти.
какие еще достоинства/недостатки? (в т.ч. с возможным влиянием на производительность алгоритма) Из двух предложенных я бы предпочел второй способ, не надо адрес вычислять, а в первом надо брать смещение, добавлять к индексу, проверять рамки...много возни. Но есть еще третий путь, самый быстрый - использовать DP-адресацию. Сам пользую, очень удобно. А структура, имхо, сама по себе будет потреблять немного ресурсов, в смысле, чтобы добраться до элемента структуры.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Dec 7 2006, 03:56
|
Частый гость
 
Группа: Новичок
Сообщений: 129
Регистрация: 4-08-06
Пользователь №: 19 327

|
Цитата(=GM= @ Dec 6 2006, 16:21)  Из двух предложенных я бы предпочел второй способ, не надо адрес вычислять, а в первом надо брать смещение, добавлять к индексу, проверять рамки...много возни. Более того, если используется несколько вызовов подряд, например Код extern DATA data[]; / **/ DATA *ptr = data+i; foo(ptr); if (isTRANSPARENT(mode)) bar(ptr); if (isREPLY(mode)) doReply(ptr); ptr->callBack(ptr); то и адрес по индексу вычисляется один раз. Цитата Но есть еще третий путь, самый быстрый - использовать DP-адресацию. Сам пользую, очень удобно. А это что за зверь?! Цитата А структура, имхо, сама по себе будет потреблять немного ресурсов, в смысле, чтобы добраться до элемента структуры. Эт' как сказать. Один мой знакомый компилятор :-) транслирует выражение вроде ptr->subStruct->subField[i]++; в долгое вычисление адреса нужного слова, загружает его в регистр, прибавляет единицу... после чего снова вычисляет адрес - куда положить!!! Явное использование промежуточных указателей дало существенный прирост на таких, казалось бы простых, операциях...
|
|
|
|
|
Dec 7 2006, 15:01
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(SasaTheProgrammer @ Dec 7 2006, 00:56)  Более того, если используется несколько вызовов подряд, например Код extern DATA data[]; / **/ DATA *ptr = data+i; foo(ptr); if (isTRANSPARENT(mode)) bar(ptr); if (isREPLY(mode)) doReply(ptr); ptr->callBack(ptr); то и адрес по индексу вычисляется один раз. Пример не наглядный, т.к. ваш указатель используется несколько раз подряд, счастлив ваш бог, и потом, вы сами явно указали процессору вычислять адрес по индексу один раз. А попробуйте хотя бы чередовать ptr1, ptr2, ptr1, ptr2 - увидите что будет(:-). Вот если бы вы передавали просто адрес, скажем адрес указателя на структуру, тогда другое дело, поскольку вычислять вообще ничего не надо! К слову. Такое впечатление, что мы говорим на разных языках, и главное - пишем, я пишу в основном на ассемблере, поэтому и говорю, в основном, об адресации на языке ассемблера, а вы, похоже, говорите об адресации на си. Цитата Цитата Но есть еще третий путь, самый быстрый - использовать DP-адресацию. Сам пользую, очень удобно.
А это что за зверь?! direct addressing mode. Заносите в дп-регистр адрес страницы и обращаетесь к 64/128 переменным, используя DP-адресацию. Там для указания переменной надо писать @variable, например,
Код movl @freq,acc ;переслать 32-битную переменную в ячейку freq dec @cont ;скрутить счетчик tclr @port,#bit ;обнулить бит в порту
Цитата Цитата А структура, имхо, сама по себе будет потреблять немного ресурсов, в смысле, чтобы добраться до элемента структуры.
Эт' как сказать. Один мой знакомый компилятор :-) транслирует выражение вроде ptr->subStruct->subField[i]++; в долгое вычисление адреса нужного слова, загружает его в регистр, прибавляет единицу... после чего снова вычисляет адрес - куда положить!!! Явное использование промежуточных указателей дало существенный прирост на таких, казалось бы простых, операциях... Ну вот, я был прав, компилер. Да будь он хоть трижды знакомый, с ним не договоришься, всё равно будет дурь переть(:-). И приходится вам, бедным сишникам, бороться не с программой и алгоритмом, а с дуроломным компилером и его разработчиками(:-). Здесь не надо отвечать, не хочу быть поджигателем очередной религиозной войны. На ассемблере всё проще, есть такие виды адресации, как, скажем, XARn(ARm), одна команда, раз - и содержимое поля структуры у вас в кармане(:-).
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Dec 8 2006, 02:40
|
Частый гость
 
Группа: Новичок
Сообщений: 129
Регистрация: 4-08-06
Пользователь №: 19 327

|
Цитата(=GM= @ Dec 7 2006, 14:01)  Пример не наглядный, т.к. ваш указатель используется несколько раз подряд, счастлив ваш бог, и потом, вы сами явно указали процессору вычислять адрес по индексу один раз. А попробуйте хотя бы чередовать ptr1, ptr2, ptr1, ptr2 - увидите что будет(:-). Вот если бы вы передавали просто адрес, скажем адрес указателя на структуру, тогда другое дело, поскольку вычислять вообще ничего не надо! Ну, так автор вопроса и спрашивал - что эффективней, адресация или индексирование по глобальному массиву. Во всяком случае, я понял вопрос именно так. А что должно случиться при чередовании указателей? Или это косвенный намёк на особенности х51 (у кого ещё есть дп?  )? Цитата К слову. Такое впечатление, что мы говорим на разных языках, и главное - пишем, я пишу в основном на ассемблере, поэтому и говорю, в основном, об адресации на языке ассемблера, а вы, похоже, говорите об адресации на си. Хмм... Думаю, что в данном контексте это несущественно. Сформулируем так: если обработка многостадийная, то адрес по индексу лучше вычислить один раз, а не передавать индекс в каждую процедуру. Независимо от языка и уровня реализации. Цитата Ну вот, я был прав, компилер. Да будь он хоть трижды знакомый, с ним не договоришься, всё равно будет дурь переть(:-). И приходится вам, бедным сишникам, бороться не с программой и алгоритмом, а с дуроломным компилером и его разработчиками(:-). Здесь не надо отвечать, не хочу быть поджигателем очередной религиозной войны.
На ассемблере всё проще, есть такие виды адресации, как, скажем, XARn(ARm), одна команда, раз - и содержимое поля структуры у вас в кармане(:-). В общем случае не совсем так. На ассемблере действительно, чаще всего можно написать и компактней и эффективней. И в ряде случаев это приходится делать, получая очень существенный выиграш. Но наглядность и отлаживаемость кода резко падают, зато трудоёмкость растёт. А если код ещё и большой, то в конечном итоге компилятор с ЯВУ обеспечивает более эффективный код, чем одуревшая команда программистов  . Причём это происходит не только (а может быть и не столько) на "скромных" архитектурах вроде х51, но и на тяжеловозах АРМ (мой случай  ). Т.е. на самом деле важно найти "узкое место" - 5..10 процентов кода - и ассемблером их, ассемблером! Остальное так, как себе, любимому, проще, на эффективности это почти не скажется. И никаких войн!
Сообщение отредактировал SasaTheProgrammer - Dec 8 2006, 02:48
|
|
|
|
|
Dec 8 2006, 12:59
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(SasaTheProgrammer @ Dec 7 2006, 23:40)  Или это косвенный намёк на особенности х51 (у кого ещё есть дп?  )? Цитата Причём это происходит не только (а может быть и не столько) на "скромных" архитектурах вроде х51, но и на тяжеловозах АРМ (мой случай  ). Вы несколько раз упомянули об архитектуре х51, это что i5051?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Dec 8 2006, 23:33
|
Частый гость
 
Группа: Новичок
Сообщений: 129
Регистрация: 4-08-06
Пользователь №: 19 327

|
Цитата(=GM= @ Dec 8 2006, 11:59)  Цитата(SasaTheProgrammer @ Dec 7 2006, 23:40)  Или это косвенный намёк на особенности х51 (у кого ещё есть дп?  )? Цитата Причём это происходит не только (а может быть и не столько) на "скромных" архитектурах вроде х51, но и на тяжеловозах АРМ (мой случай  ). Вы несколько раз упомянули об архитектуре х51, это что i5051? Да. А резве подразумевалось что-то другое?
|
|
|
|
|
Dec 9 2006, 00:55
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(=GM= @ Dec 8 2006, 12:59)  Вы несколько раз упомянули об архитектуре х51, это что i5051? Может все-таки классическое ядро 8051... Или я не в теме?..
--------------------
شامل
|
|
|
|
|
Dec 9 2006, 15:12
|

Electrical Engineer
     
Группа: СуперМодераторы
Сообщений: 2 163
Регистрация: 4-10-04
Пользователь №: 778

|
Цитата(Edmundo @ Dec 9 2006, 00:55)  Может все-таки классическое ядро 8051... Или я не в теме?.. для присоединившихся: изначально под C5000 я имел в виду С54хх и С55хх от TI. интересовала реализация на языке Си. хотя использование Си в какой-то мере подразумевает CPU-independent обсуждение. благодаря ответам, вопрос прояснился.. теперь немного об автоматизации второго способа (через передачу указателя на адрес структуры): если надо обрабатывать 32 канала, то в 1м способе просто могли организовывать цикл по 32, а переменную цикла передавать в функцию обработки ка кномер канала. а в ситуации с передачей адреса указателя на структуру быть как?.. первое что приходит: заводить контекст канала всеже как _массив_ структур, а адрес структуры вычислять как: Код TYPE_OF_STRUC_CH_CONTEXT struct_ch_context[32]; int *curr_struc_addr; void call_ch_process(int **paddr); ... for (i = 0; i < 32; i++) { curr_struc_addr = struct_ch_context + i*sizeof(TYPE_OF_STRUC_CH_CONTEXT); call_ch_process(*curr_struc_addr); } вот как-то так чтоли получается..
--------------------
|
|
|
|
|
Dec 9 2006, 23:39
|
Частый гость
 
Группа: Новичок
Сообщений: 129
Регистрация: 4-08-06
Пользователь №: 19 327

|
Цитата(Doka @ Dec 9 2006, 14:12)  хотя использование Си в какой-то мере подразумевает CPU-independent обсуждение. Угу. Я, собственно, именно из таких соображений и отвечал. Цитата Код TYPE_OF_STRUC_CH_CONTEXT struct_ch_context[32]; int *curr_struc_addr; void call_ch_process(int **paddr); ... for (i = 0; i < 32; i++) { curr_struc_addr = struct_ch_context + i*sizeof(TYPE_OF_STRUC_CH_CONTEXT); call_ch_process(*curr_struc_addr); } вот как-то так чтоли получается.. НЕЕЕЕТ!!! Во-первых, не нужно умножать на размер структуры - компилятор сделает это сам - мы ведь о Си говорим? Т.е. это просто ошибка, указатель унесёт страшно даже подумать куда  . Во-вторых, функция объявлена как принимающая указатель на указатель на int (откуда?!), а что ей передаётся в действительности?!
Сообщение отредактировал SasaTheProgrammer - Dec 10 2006, 00:09
|
|
|
|
|
Dec 10 2006, 11:19
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(Doka @ Dec 9 2006, 15:12)  для присоединившихся: изначально под C5000 я имел в виду С54хх и С55хх от TI. интересовала реализация на языке Си. хотя использование Си в какой-то мере подразумевает CPU-independent обсуждение. благодаря ответам, вопрос прояснился.. теперь немного об автоматизации второго способа (через передачу указателя на адрес структуры): если надо обрабатывать 32 канала, то в 1м способе просто могли организовывать цикл по 32, а переменную цикла передавать в функцию обработки ка кномер канала. а в ситуации с передачей адреса указателя на структуру быть как?.. первое что приходит: заводить контекст канала всеже как _массив_ структур, а адрес структуры вычислять как: Код TYPE_OF_STRUC_CH_CONTEXT struct_ch_context[32]; int *curr_struc_addr; void call_ch_process(int **paddr); ... for (i = 0; i < 32; i++) { curr_struc_addr = struct_ch_context + i*sizeof(TYPE_OF_STRUC_CH_CONTEXT); call_ch_process(*curr_struc_addr); } вот как-то так чтоли получается.. Я просто не встречал ядро i5051, а про С5000 понятно. Но про код не понял -- почему не сделать так? Код TYPE_OF_STRUC_CH_CONTEXT struct_ch_context[32]; void call_ch_process(void *paddr); ... for (i = 0; i < 32; i++) { call_ch_process(&struct_ch_context[i]); } ... void call_ch_process(void *paddr) { TYPE_OF_STRUC_CH_CONTEXT *pstruct = (TYPE_OF_STRUC_CH_CONTEXT *) paddr; pstruct->... ... } Или вам внутри call_ch_process нужно обязательно знать номер канала? Тогда проще добавить его как аргумент функции.
--------------------
شامل
|
|
|
|
|
Dec 10 2006, 11:52
|

Electrical Engineer
     
Группа: СуперМодераторы
Сообщений: 2 163
Регистрация: 4-10-04
Пользователь №: 778

|
Цитата(Edmundo @ Dec 10 2006, 11:19)  Но про код не понял -- почему не сделать так? Код TYPE_OF_STRUC_CH_CONTEXT struct_ch_context[32]; void call_ch_process(void *paddr); ... for (i = 0; i < 32; i++) { call_ch_process(&struct_ch_context[i]); } ... void call_ch_process(void *paddr) { TYPE_OF_STRUC_CH_CONTEXT *pstruct = (TYPE_OF_STRUC_CH_CONTEXT *) paddr; pstruct->... ... } Или вам внутри call_ch_process нужно обязательно знать номер канала? Тогда проще добавить его как аргумент функции. за пример большое спасибо - просто почти не работал со структурами на Си - поэтому некий сумбур в голове. номер канала действительно желательно знать - ибо call_ch_process вызывает из себя процедуры, обработка в некоторых из них также завязана на контекст канала. Но номер канала планирую хранить как поле структуры , прописывая его при инициализации (ну а там уж передавать - либо номер канала, либо указатель на структуру). еще такой исследовательский вопрос: когда я смотрел как это в принципе делают, то в нек-х случаях передают адрес указателя на структуру, а не указатель на структуру - для чего это может быть полезно? (единственно что напрашивается - возможность изменять само содержимое указателя)
--------------------
|
|
|
|
|
Dec 10 2006, 14:11
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(Doka @ Dec 10 2006, 11:52)  за пример большое спасибо - просто почти не работал со структурами на Си - поэтому некий сумбур в голове.
номер канала действительно желательно знать - ибо call_ch_process вызывает из себя процедуры, обработка в некоторых из них также завязана на контекст канала. Но номер канала планирую хранить как поле структуры , прописывая его при инициализации (ну а там уж передавать - либо номер канала, либо указатель на структуру).
еще такой исследовательский вопрос: когда я смотрел как это в принципе делают, то в нек-х случаях передают адрес указателя на структуру, а не указатель на структуру - для чего это может быть полезно? (единственно что напрашивается - возможность изменять само содержимое указателя) У меня тоже только это напрашивается. Например если память под структуру выделяется (или перемещается) внутри этой функции. А вообще про то, как организовывать многоканальную обработку, можно посмотреть в техасовском XDAIS (если вы еще с ним не знакомы, конечно  ). Сам стандарт в нашей лаборатории по разным причинам не пошел, но кое-какие идеи оттуда почерпнуть имхо можно.
--------------------
شامل
|
|
|
|
|
Dec 10 2006, 14:35
|
Частый гость
 
Группа: Новичок
Сообщений: 129
Регистрация: 4-08-06
Пользователь №: 19 327

|
Начнём с конца. Цитата(Doka @ Dec 10 2006, 10:52)  еще такой исследовательский вопрос: когда я смотрел как это в принципе делают, то в нек-х случаях передают адрес указателя на структуру, а не указатель на структуру - для чего это может быть полезно? (единственно что напрашивается - возможность изменять само содержимое указателя) Указатель передают в двух случаях. Во-первых, есть существеноое различие, для которого применяют специальные термины - "передача по ссылке"/"передача по значению". При "передаче по значению" функция получает свою копию данных, с которой можно делать всё что угодно. При "передаче по ссылке" любые изменения производятся в самих данных. Для коротких, неструктурных данных принято "передавать по ссылке" только те данные, которые нужно менять внутри функции (так, чтобы изменения были видны снаружи). В этом случае передача по ссылке - необходимые накладные расходы, на "разименование указателя" тратятся драгоценные такты. Во-вторых, если речь идёт о структурах/объединениях/массивах (если передать в функцию массив, то на самом деле она получит указатель на первый элемент). Тут оказывается выгоднее передать указатель, чем запихивать структуру в регистры/стек. Т.е. простое программистское правило: "видишь передаваемый указатель - это точно out-параметер, возможно он ещё и in" в данном случае нарушается. Нужно очень вниматеьно обращатся с переданой таким образом структурой и обязательно (!!!) документировать в комментариях меняет ли функция что-либо, а если да - то какие поля. Цитата номер канала действительно желательно знать - ибо call_ch_process вызывает из себя процедуры, обработка в некоторых из них также завязана на контекст канала. Но номер канала планирую хранить как поле структуры , прописывая его при инициализации (ну а там уж передавать - либо номер канала, либо указатель на структуру). Вся прелесть передачи указателя в том, что номер знать не нужно. Другим процедурам также передаётся указатель. Структуры могут вообще не лежать в массиве и нахождение указателя по номеру может быть нетривиальной задачей. Но она будет выполняться отлько один раз, "на самом верху" обработки. Цитата за пример большое спасибо - просто почти не работал со структурами на Си - поэтому некий сумбур в голове. Это не структуры, это адресная арифметика. К этому нужно привыкнуть, да.
|
|
|
|
|
Dec 10 2006, 16:18
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(SasaTheProgrammer @ Dec 10 2006, 14:35)  Тут оказывается выгоднее передать указатель, чем запихивать структуру в регистры/стек. Т.е. простое программистское правило: "видишь передаваемый указатель - это точно out-параметер, возможно он ещё и in" в данном случае нарушается. Нужно очень вниматеьно обращатся с переданой таким образом структурой и обязательно (!!!) документировать в комментариях меняет ли функция что-либо, а если да - то какие поля. Вопроса о передаче структуры "по значению" не стояло. Прочитайте вопрос внимательнее: Цитата(Doka @ Dec 10 2006, 11:52)  ... адрес указателя на структуру, а не указатель на структуру ... Цитата(SasaTheProgrammer @ Dec 10 2006, 14:35)  Вся прелесть передачи указателя в том, что номер знать не нужно. Нужно ли знать номер канала -- зависит от конкретной задачи. Передать его внутри структуры -- вполне красивое решение.
--------------------
شامل
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|