|
Лишние NOP в ассемблерном коде |
|
|
|
 |
Ответов
|
Oct 23 2007, 12:04
|

Эксперт
    
Группа: Свой
Сообщений: 1 467
Регистрация: 25-06-04
Пользователь №: 183

|
Цитата(Degun @ Oct 23 2007, 15:54)  Code Composer Studio v 3.3; Процессор DM642 на evalution board. Имеется программка, написанная на C++. После анализа её ассемблерного кода выяснилось, что после многих команд (LDW, ADD, CMPLT, AND, LDHU и др.) компилятор вставляет команду NOP, что естественно замедляет функционирование программы. Для чего это? Можно ли отключить вставку операторов NOP в ассемблерный код? Это не ассемблерный код, а выход С-компилятора. У TI такой подход, что программист (или компилятор) должен следить за длительностью выполнения инструкций (latency). Например, если умножение требует 5 тактов, то нужно пять тактов и ждать, в противном случае Вы выхватываете из конвейера неверный результат (что, однако, никто Вам запретить не может). Вот компилятор и борется с "открытым конвейером" Есть единственный гарантированый способ избежать вставки NOP в ассемблерный код - написать самому на ассемблере, так чтобы без NOPов ;-) TMS серии 6х - это ведь кубик Рубика
|
|
|
|
|
Oct 23 2007, 12:15
|
Частый гость
 
Группа: Новичок
Сообщений: 84
Регистрация: 4-09-07
Из: Москва
Пользователь №: 30 277

|
Цитата(fontp @ Oct 23 2007, 16:04)  Это не ассемблерный код, а выход С-компилятора. А разве это не одно и тоже? Цитата(fontp @ Oct 23 2007, 16:04)  У TI такой подход, что программист (или компилятор) должен следить за длительностью выполнения инструкций (latency). Например, если умножение требует 5 тактов, то нужно пять тактов и ждать, в противном случае Вы выхватываете из конвейера неверный результат (что, однако, никто Вам запретить не может). Вот компилятор и борется с "открытым конвейером" Есть единственный гарантированый способ избежать вставки NOP в ассемблерный код - написать самому на ассемблере, так чтобы без NOPов ;-) TMS серии 6х - это ведь кубик Рубика Не совсем понятно. Если умножению, например, требуется 5 тактов, то соответствующая команда и будет выполняться необходимое кол-во тактов и только после после этого перейдёт к выполнению следующей. Или переход к выполнению следующей команды осуществляется сразу, а результат умножения будет готов только через 5 тактов?
|
|
|
|
|
Oct 26 2007, 12:06
|
Частый гость
 
Группа: Новичок
Сообщений: 84
Регистрация: 4-09-07
Из: Москва
Пользователь №: 30 277

|
Что можно сделать или оптимизировать в функции ниже в плане генерации оптимального кода для DSP-процессора? Код int SplitImage2Areas(unsigned char **Image, int **AreasNumb, int *Areas2Mode, int Width, int Height, int Thres1, int Thres2) { if ((Image==0)||(Width<=0)||(Height<=0)||(AreasNumb==0)) return -1;
int iPrevAreaNumbL=-1; //Номер области предыдущей левой точки int iPrevModeNumbL=-1; //Номер моды предыдущей левой точки int iPrevAreaNumbU=-1; //Номер области предыдущей верхней точки int iPrevModeNumbU=-1; //Номер моды предыдущей верхней точки int iPrevAreaNumbUL=-1; //Номер области предыдущей верхней левой точки int iPrevModeNumbUL=-1; //Номер моды предыдущей верхней левой точки int iPrevAreaNumbUR=-1; //Номер области предыдущей верхней правой точки int iPrevModeNumbUR=-1; //Номер моды предыдущей верхней правой точки int iAreasCount=0; //Счётчик кол-ва областей int i, j, y, x, iNumb[4], iNumbCount, iDelta, iTmp; int iCurrPixel, iCurrAreaNumb, iCurrModeNumb; //Изображение последовательно просматривается по строкам //для отнесения каждого пиксела к определённой области for (y=0; y<Height; y++) for (x=0; x<Width; x++) { //Значение яркости текущего пикселя iCurrPixel=Image[y][x]; //Номер области текущей точки iCurrAreaNumb=-1; //Номер моды текущей точки iCurrModeNumb=(iCurrPixel<Thres1?0:(iCurrPixel>Thres2?1:-1)); //Определение параметров верхней правой точки if ((y>0)&&(x<(Width-1))) { iPrevAreaNumbUR=AreasNumb[y-1][x+1]; iPrevModeNumbUR=Areas2Mode[iPrevAreaNumbUR]; } //В зависимости от того является ли точка переходной if (iCurrModeNumb>=0) { //Эта точка не является переходной ни к одной из мод //Просмотр всех соседних уже размеченных ранее точек //для возможного определения номера области текущей точки if ((x>0)&&(iCurrModeNumb==iPrevModeNumbL)) { iCurrAreaNumb=iPrevAreaNumbL; //Левая точка } else if (y>0) { //Верхняя строка if (iCurrModeNumb==iPrevModeNumbU) { iCurrAreaNumb=iPrevAreaNumbU; //Верхняя точка } else if ((x>0)&&(iCurrModeNumb==iPrevModeNumbUL)) { iCurrAreaNumb=iPrevAreaNumbUL; //Верхняя левая точка } else if ((x<(Width-1))&&(iCurrModeNumb==iPrevModeNumbUR)) { iCurrAreaNumb=iPrevAreaNumbUR; //Верхняя правая точка } } } else { //Текущая точка является переходной к любой области //Выбор наиболее близкой области iDelta=iTmp=-1; if (x>0) { //Левая точка iCurrAreaNumb=iPrevAreaNumbL; iDelta=abs(Image[y][x-1]-iCurrPixel); } if (y>0) { //Верхняя строка //Верхняя точка iTmp=abs(Image[y-1][x]-iCurrPixel); if ((iDelta<0)||(iDelta>iTmp)) { iCurrAreaNumb=iPrevAreaNumbU; iDelta=iTmp; } if (x>0) { //Верхняя левая точка iTmp=abs(Image[y-1][x-1]-iCurrPixel); if (iDelta>iTmp) { iCurrAreaNumb=iPrevAreaNumbUL; iDelta=iTmp; } } if (x<(Width-1)) { //Верхняя правая точка iTmp=abs(Image[y-1][x+1]-iCurrPixel); if (iDelta>iTmp) { iCurrAreaNumb=iPrevAreaNumbUR; iDelta=iTmp; } } } //Проверка на верхнюю левую точку всего изображения if (iCurrAreaNumb>=0) iCurrModeNumb=Areas2Mode[iCurrAreaNumb]; else //Нужно добавить новую область с нулевой модой iCurrModeNumb=0; } //Если это новая область if (iCurrAreaNumb<0) { //Добавление нового объекта в коллекцию iCurrAreaNumb=iAreasCount++; Areas2Mode[iCurrAreaNumb]=iCurrModeNumb; } //Установка номера области текущей точки AreasNumb[y][x] = iCurrAreaNumb; //Сканирование окрестных точек для выяснения граничащих областей iNumbCount=0; if ((x==0)||(iPrevAreaNumbL!=iCurrAreaNumb)) { //Просмотр левой точки if ((x>0)&&(iCurrModeNumb==iPrevModeNumbL)&&(iCurrAreaNumb!=iPrevAreaNumbL)) iNumb[iNumbCount++]=iPrevAreaNumbL; //Просмотр верхней левой точки if ((y>0)&&(x>0)&&(iCurrModeNumb==iPrevModeNumbUL)&&(iCurrAreaNumb!=iPrevAreaNumbUL)) iNumb[iNumbCount++]=iPrevAreaNumbUL; //Просмотр верхней точки if ((y>0)&&(iCurrModeNumb==iPrevModeNumbU)&&(iCurrAreaNumb!=iPrevAreaNumbU)) iNumb[iNumbCount++]=iPrevAreaNumbU; } //Сканирование верхней правой точки (в любом случае независимо от iPrevAreaNumb!!!) if ((y>0)&&(x<(Width-1))&&(iCurrModeNumb==iPrevModeNumbUR)&&(iCurrAreaNumb!=iPrevAreaNumbUR)) iNumb[iNumbCount++]=iPrevAreaNumbUR; //Добавление найденных граничных областей for (i=0; i<iNumbCount; i++) { iTmp=iNumb[i]; bool bFind=false; for (j=0; j<i; j++) if (iNumb[j]==iTmp) { bFind=true; break; } if (!bFind) { //Здесь области добавляются к списку соседних областей } } //Запоминание номера области и моды для левой точки iPrevAreaNumbL=iCurrAreaNumb; iPrevModeNumbL=iCurrModeNumb; //Запоминание номера области и моды для верхней левой точки iPrevAreaNumbUL=iPrevAreaNumbU; iPrevModeNumbUL=iPrevModeNumbU; //Запоминание номера области и моды для верхней точки iPrevAreaNumbU=iPrevAreaNumbUR; iPrevModeNumbU=iPrevModeNumbUR; }
return iAreasCount; }
Сообщение отредактировал Degun - Oct 26 2007, 12:11
|
|
|
|
|
Nov 16 2007, 10:07
|

Частый гость
 
Группа: Свой
Сообщений: 86
Регистрация: 22-03-07
Из: Санкт-Петербург
Пользователь №: 26 406

|
Цитата(Degun @ Oct 26 2007, 16:06)  Что можно сделать или оптимизировать в функции ниже в плане генерации оптимального кода для DSP-процессора? Код int SplitImage2Areas(unsigned char **Image, int **AreasNumb, int *Areas2Mode, int Width, int Height, int Thres1, int Thres2) [поудалял // qxov] Я хотел бы попытался подсказать, как можно улучшить этот код, но для этого желательно на словах объяснить, что он должен делать - код не прозрачен и практически не читается, к сожалению. Подскажите, если задача не потеряла актуальность. Цитата(Edmundo @ Oct 24 2007, 16:36)  Вы читали про ядро, про 8 "вычислителей", про кросс-пути и про параллельное выполнение? И еще -- если поиграться оптимизацией -- можно получить неплохой код, не обязательно бросаться писать на АСМе. Ну да C vs. ASM -- это из другой оперы  На начальном этапе оптимизации многое из этого излишне. Скажем, кросс-пути - это вообще в последнюю очередь должно волновать голову, полно гораздо более значимых моментов. Цитата(Degun @ Oct 31 2007, 00:12)  Как известно у TI C6000-го семейства 8 конвейеров. А вообще приведённый код функции будет выполняться на одном конвейере или на 8-ми. Т. е. будет ли компилятор загружать автоматически все конвейеры или только один и необходимо предпринимать специальные меры, чтобы загрузить остальные 7? У этого семейства 8 юнитов, по 2 каждого типа: .L, .S, .D, .M. В частности, в SPRU732C Appendix B есть таблица "Mapping Between Instruction and Functional Unit". Например, в .M юнитах выполняются, в основном, умножения, в .L - логические операции и т.д. То есть, нельзя загрузить все юниты, если не используются соответствующие инструкции. Компилятор очень хорошо оптимизирует код, но только в том случае, если ему предоставить такую возможность - дать знать, сколько раз (обычно) выполняются циклы, вытащить из циклов вызовы функций и т.д. Большое количество разных if - смерть для оптимизатора. Стоит заметить, что у этих процессоров все инструкции являются условными, что можно грамотно применить при написании кода, получив ускорение даже в несколько раз, по сравнению с написанием "в лоб", при этом не приходится даже серьезно модифицировать алгоритм.
|
|
|
|
|
Nov 16 2007, 13:08
|
Частый гость
 
Группа: Новичок
Сообщений: 84
Регистрация: 4-09-07
Из: Москва
Пользователь №: 30 277

|
Цитата(qxov @ Nov 16 2007, 13:07)  Я хотел бы попытался подсказать, как можно улучшить этот код, но для этого желательно на словах объяснить, что он должен делать - код не прозрачен и практически не читается, к сожалению. Подскажите, если задача не потеряла актуальность. Задача состоит в следующем: на вход функции поступает полутоновое (серое) 8-ми битовое изображение Image размерами Height и Width. Типичный пример изображения - звёзды на фоне космического пространства. Необходимо разбить изображение на непересекающиеся пронумерованные области в соответствии с двуми порогами: Thr1 - порог фона (нижний порог); Thr2 - порог объектов (верхний порог). Те пикселы, которые находятся между порогами Thr1 и Thr2 (т. е. Thr1 < PixelValue < Thr2) являются переходными и могут быть отнесены к любой ближайшей наиболее близкой (с точки зрения близости значений пикселов) области. На выходе функции в массиве AreasNumbBuf для каждого пиксела сохраняется номер области, к которой принадлежит этот пиксель (это может быть или космическое пространство или звезда или НЛО  ). Алгоритм с последней публикации был достаточно сильно изменён, поэтому привожу его заново. Но несмотря на значительную оптимизацию его быстродействие на процессоре DM642 оставляет желать лучшего. Например для изображения размерами 640*480 он выполняется порядка 0.6 сек, что неприемлемо. Планировалось, что он должен выполняться порядка 20 мсек (50 Гц). Код #include <stdlib.h>
//Максимальное кол-во областей в изображении #define MAX_AREAS 1000 #define min(x,y) (x<y?x:y)
//Структура хранения информации об областях typedef struct TAreaInfo { //Номер кластера short iNumber; //Номер моды short iMode; //Счётчик мощности моды int iCount; } TAreaInfo;
//Счётчики количества областей в изображении и в контейнере static int iAreasCount=0, iAreasInfoCount=0;
//Ограниченный массив структур описателей областей!!! static TAreaInfo AreasInfo[MAX_AREAS+1];
//Таблица соответствия значений пикселов модам гистограммы static int ModeNumb4Pix[256];
//Функция создания новой области static inline int AddNewAreaInfo(const int iModeNumb) { // if (iAreasInfoCount>=MAX_AREAS) return -1; iAreasCount++; AreasInfo[iAreasInfoCount].iMode=iModeNumb; AreasInfo[iAreasInfoCount].iNumber=-1; AreasInfo[iAreasInfoCount].iCount=0; return iAreasInfoCount++; }
/*!\brief Разбиение изображения на непересекающиеся области * \param Image - исходное изображение * \param Height - высота изображения * \param Width - ширина изображение * \param AreasNumbBuf - буфер результата, отражающий номера областей каждого из пикселов * \param Thr1 - нижний порог * \param Thr2 - верхний порог * \result Количество непересекающихся областей в изображении */ int SplitImage2Areas( register unsigned char ** __restrict Image, register int Height, register int Width, register int ** __restrict AreasNumbBuf, register int Thr1, register int Thr2) { //Изображение последовательно просматривается по строкам //для отнесения каждого пиксела к определённой области //Вычисление площади, занимаемой каждой областью и модой register int iPrevAreaNumbL=-1; //Номер области предыдущей левой точки register int iPrevModeNumbL=-1; //Номер моды предыдущей левой точки register int iPrevAreaNumbU=-1; //Номер области предыдущей верхней точки register int iPrevModeNumbU=-1; //Номер моды предыдущей верхней точки register int iPrevAreaNumbUL=-1; //Номер области предыдущей верхней левой точки register int iPrevModeNumbUL=-1; //Номер моды предыдущей верхней левой точки register int iPrevAreaNumbUR=-1; //Номер области предыдущей верхней правой точки register int iPrevModeNumbUR=-1; //Номер моды предыдущей верхней правой точки //Временные переменные register int i, y, x, iSrcIndex, iDstIndex, iDelta, iTmp; register int iCurrPixel, iCurrAreaNumb, iCurrModeNumb; register TAreaInfo * __restrict pSrcObj, * __restrict pDstObj, * __restrict pTmpObj;
//Проверка корректности входных параметров if ((Image==0)||(Width<=0)||(Height<=0)||(ModeNumb4Pix==0)||(AreasNumbBuf==0)) return -1; //Формирование таблицы мод пикселей for (i=0; i<256; i++) { if (i<Thr1) ModeNumb4Pix[i]=0; else if (i>=Thr2) ModeNumb4Pix[i]=1; else ModeNumb4Pix[i]=-1; } //Обнуление счётчиков кол-ва областей iAreasCount=iAreasInfoCount=0; //Обработка верхней левой точки изображения iCurrPixel=Image[0][0]; iCurrModeNumb=ModeNumb4Pix[iCurrPixel]; if (iCurrModeNumb<0) { //Сканирование зигзагом окрестных точек для //выявления ближайшей с установленной модой iDelta=min(Width,Height); for (i=1; i<iDelta; i++) { iSrcIndex=-1; for (y=i, x=0; y>=0; y--, x++) { iDstIndex=Image[y][x]; iTmp=ModeNumb4Pix[iDstIndex]; if (iTmp<0) continue; iDstIndex=abs(iDstIndex-iCurrPixel); if ((iSrcIndex<0)||(iSrcIndex>iDstIndex)) { iSrcIndex=iDstIndex; iCurrModeNumb=iTmp; } } //Нашли подходящую точку - выход из поиска if (iCurrModeNumb>=0) break; } //Если точек нет, то нулевая мода if (iCurrModeNumb<0) iCurrModeNumb=0; } iCurrAreaNumb=AddNewAreaInfo(iCurrModeNumb); AreasNumbBuf[0][0]=iCurrAreaNumb; //Обработка первой верхней строки изображения, //начиная со второго пиксела строки for (x=1; x<Width; x++) { //Запоминание номера области и моды для левой точки iPrevAreaNumbL=iCurrAreaNumb; iPrevModeNumbL=iCurrModeNumb; //Номер моды текущей точки iCurrModeNumb=ModeNumb4Pix[Image[0][x]]; //В зависимости от наличия моды if (iCurrModeNumb<0) { iCurrModeNumb=iPrevModeNumbL; iCurrAreaNumb=iPrevAreaNumbL; } else if (iCurrModeNumb==iPrevModeNumbL) { iCurrAreaNumb=iPrevAreaNumbL; } else { //Добавление новой области iCurrAreaNumb=AddNewAreaInfo(iCurrModeNumb); } //Установка номера области текущей точки AreasNumbBuf[0][x] = iCurrAreaNumb; //Инкремент счётчика площади, занимаемой областью AreasInfo[iCurrAreaNumb].iCount++; } //Декремент ширины изображения для увеличения скорости обработки Width--; //Цикл по всем точкам изображения for (y=1; y<Height; y++) { //Установка начального значения для верхней левой точки iPrevAreaNumbUL=AreasNumbBuf[y-1][0]; iPrevModeNumbUL=AreasInfo[iPrevAreaNumbUL].iMode; //Установка начального значения для верхней точки iPrevAreaNumbU=AreasNumbBuf[y-1][1]; iPrevModeNumbU=AreasInfo[iPrevAreaNumbU].iMode; //Значение яркости первого пикселя строки iCurrPixel=Image[y][0]; //Значение моды первого пикселя строки iPrevModeNumbL=ModeNumb4Pix[iCurrPixel]; //В зависимости от признака переходности пиксела if (iPrevModeNumbL<0) { if (abs(iCurrPixel-Image[y-1][0])<abs(iCurrPixel-Image[y-1][1])) { iPrevModeNumbL=iPrevModeNumbUL; iPrevAreaNumbL=iPrevAreaNumbUL; } else { iPrevModeNumbL=iPrevModeNumbU; iPrevAreaNumbL=iPrevAreaNumbU; } } else if (iPrevModeNumbL==iPrevModeNumbUL) iPrevAreaNumbL=iPrevAreaNumbUL; //Верхняя левая точка else if (iPrevModeNumbL==iPrevModeNumbU) iPrevAreaNumbL=iPrevAreaNumbU; //Верхняя точка else { //Добавление новой области iPrevAreaNumbL=AddNewAreaInfo(iPrevModeNumbL); } //Установка номера области первого пиксела строки AreasNumbBuf[y][0] = iPrevAreaNumbL; //Инкремент счётчика площади, занимаемой областью AreasInfo[iPrevAreaNumbL].iCount++; //Обработка очередной строки изображения for (x=1; x<Width; x++) { //Определение параметров верхней правой точки iPrevAreaNumbUR=AreasNumbBuf[y-1][x+1]; iPrevModeNumbUR=AreasInfo[iPrevAreaNumbUR].iMode; //Значение яркости текущего пикселя iCurrPixel=Image[y][x]; //Номер моды текущей точки iCurrModeNumb=ModeNumb4Pix[iCurrPixel]; //В зависимости от того является ли точка переходной if (iCurrModeNumb<0) { //Текущая точка является переходной к любой области //Перебор всех точек окрестности и выбор наиболее близкой области //Левая точка iDelta=abs(Image[y][x-1]-iCurrPixel); iCurrAreaNumb=iPrevAreaNumbL; iCurrModeNumb=iPrevModeNumbL; //Верхняя точка iTmp=abs(Image[y-1][x]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbU; iCurrModeNumb=iPrevModeNumbU; } //Верхняя левая точка iTmp=abs(Image[y-1][x-1]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbUL; iCurrModeNumb=iPrevModeNumbUL; } //Верхняя правая точка iTmp=abs(Image[y-1][x+1]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbUR; iCurrModeNumb=iPrevModeNumbUR; } } //Эта точка не является переходной ни к одной из мод //Просмотр всех соседних уже размеченных ранее точек //для возможного определения номера области текущей точки else if (iCurrModeNumb==iPrevModeNumbL) iCurrAreaNumb=iPrevAreaNumbL; //Левая точка else if (iCurrModeNumb==iPrevModeNumbUL) iCurrAreaNumb=iPrevAreaNumbUL; //Верхняя левая точка else if (iCurrModeNumb==iPrevModeNumbU) iCurrAreaNumb=iPrevAreaNumbU; //Верхняя точка else if (iCurrModeNumb==iPrevModeNumbUR) iCurrAreaNumb=iPrevAreaNumbUR; //Верхняя правая точка else { //Добавление новой области iCurrAreaNumb=AddNewAreaInfo(iCurrModeNumb); } //Установка номера области текущей точки AreasNumbBuf[y][x] = iCurrAreaNumb; //Объект области в дереве pSrcObj=&AreasInfo[iCurrAreaNumb]; //Инкремент счётчика площади, занимаемой областью pSrcObj->iCount++; //Сканирование верхней правой точки для добавления её в список соседних областей if ((iCurrModeNumb==iPrevModeNumbUR)&&(iCurrAreaNumb!=iPrevAreaNumbUR)) { //Объект области предыдущей ссылки pDstObj=&AreasInfo[iPrevAreaNumbUR]; //Всего четыре возможных варианта if (pSrcObj->iNumber<0) { if (pDstObj->iNumber>=0) { //Только добавляется ссылка на ссылочную область pSrcObj->iNumber=pDstObj->iNumber; //Декремент кол-ва областей iAreasCount--; } else { //Обе области являются доменными iTmp=min(iCurrAreaNumb,iPrevAreaNumbUR); pSrcObj->iNumber=iTmp; pDstObj->iNumber=iTmp; //Декремент кол-ва областей iAreasCount--; } } else //if (pSrcObj->iNumber>=0) { if (pDstObj->iNumber<0) { //Только добавляется ссылка на ссылочную область pDstObj->iNumber=pSrcObj->iNumber; //Декремент кол-ва областей iAreasCount--; } else { iSrcIndex=pSrcObj->iNumber; iDstIndex=pDstObj->iNumber; if (iSrcIndex!=iDstIndex) { //Это самый трудоёмкий случай. //Но, к счастью, самый редкий! //Необходимо объединить две области for (i=0; i<iAreasInfoCount; i++) { pTmpObj=&AreasInfo[i]; if (pTmpObj->iNumber==iSrcIndex) pTmpObj->iNumber=iDstIndex; } //Декремент кол-ва областей iAreasCount--; } } } } //Запоминание номера области и моды для левой точки iPrevAreaNumbL=iCurrAreaNumb; iPrevModeNumbL=iCurrModeNumb; //Запоминание номера области и моды для верхней левой точки iPrevAreaNumbUL=iPrevAreaNumbU; iPrevModeNumbUL=iPrevModeNumbU; //Запоминание номера области и моды для верхней точки iPrevAreaNumbU=iPrevAreaNumbUR; iPrevModeNumbU=iPrevModeNumbUR; } //Значение яркости последнего пикселя строки iCurrPixel=Image[y][Width]; //Значение моды последнего пикселя строки iCurrModeNumb=ModeNumb4Pix[iCurrPixel]; //В зависимости от наличия моды if (iCurrModeNumb<0) { //Левая точка iDelta=abs(Image[y][x-1]-iCurrPixel); iCurrAreaNumb=iPrevAreaNumbL; iCurrModeNumb=iPrevModeNumbL; //Верхняя левая точка iTmp=abs(Image[y-1][x-1]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbUL; iCurrModeNumb=iPrevModeNumbUL; } //Верхняя точка iTmp=abs(Image[y-1][x]-iCurrPixel); if (iDelta>iTmp) { iDelta=iTmp; iCurrAreaNumb=iPrevAreaNumbU; iCurrModeNumb=iPrevModeNumbU; } } else if (iCurrModeNumb==iPrevModeNumbL) iCurrAreaNumb=iPrevAreaNumbL; //Левая точка else if (iCurrModeNumb==iPrevModeNumbUL) iCurrAreaNumb=iPrevAreaNumbUL; //Верхняя левая точка else if (iCurrModeNumb==iPrevModeNumbU) iCurrAreaNumb=iPrevAreaNumbU; //Верхняя правая точка else { //Добавление новой области iCurrAreaNumb=AddNewAreaInfo(iCurrModeNumb); } //Установка номера области последнего пикселя строки AreasNumbBuf[y][Width] = iCurrAreaNumb; //Инкремент счётчика площади, занимаемой областью AreasInfo[iCurrAreaNumb].iCount++; } //Восстановление исходной ширины изображения Width++;
//Упорядочивание переадресации областей (именно здесь)!!!!! for (i=0; i<iAreasInfoCount; i++) { pTmpObj=&AreasInfo[i]; iTmp=pTmpObj->iNumber; if (iTmp<0) { //Это независимый кластер pTmpObj->iNumber=i; } else if (iTmp!=i) { //Это не кластерная область AreasInfo[iTmp].iCount+=pTmpObj->iCount; //Обнуление счётчика - выключение области pTmpObj->iCount=0; } }
//Могут оставаться независимые области с индексами больше iAreasCount for (iDstIndex=0, iSrcIndex=iAreasCount; iSrcIndex<iAreasInfoCount; iSrcIndex++) { //Если эта область уже переадресована - все нормально pSrcObj=&AreasInfo[iSrcIndex]; if ((pSrcObj==NULL)||(pSrcObj->iCount==0)) continue; //Поиск индекса для переадресации for (; iDstIndex<iAreasCount; iDstIndex++) { pDstObj=&AreasInfo[iDstIndex]; if ((pDstObj!=NULL)&&(pDstObj->iCount==0)) break; } //Сохранение указателя на моду pDstObj->iMode=pSrcObj->iMode; //Коррекция счётчиков мощности областей pDstObj->iCount=pSrcObj->iCount; pSrcObj->iCount=0; //Установка ссылки данной области на переадресованную pSrcObj->iNumber=iDstIndex; //Замена всех ссылок на эту область!!!!!!!! for (i=0; i<iAreasInfoCount; i++) { pTmpObj=&AreasInfo[i]; if (pTmpObj->iNumber==iSrcIndex) pTmpObj->iNumber=iDstIndex; } }
//Переписывание индексов областей на новые переназначенные for (y=0; y<Height; y++) for (x=0; x<Width; x++) { iTmp=AreasNumbBuf[y][x]; iTmp=AreasInfo[iTmp].iNumber; AreasNumbBuf[y][x]=iTmp; }
return iAreasCount; }
|
|
|
|
|
Nov 18 2007, 13:15
|

Частый гость
 
Группа: Свой
Сообщений: 86
Регистрация: 22-03-07
Из: Санкт-Петербург
Пользователь №: 26 406

|
Цитата(Degun @ Nov 16 2007, 16:08)  Алгоритм с последней публикации был достаточно сильно изменён, поэтому привожу его заново. Но несмотря на значительную оптимизацию его быстродействие на процессоре DM642 оставляет желать лучшего. Например для изображения размерами 640*480 он выполняется порядка 0.6 сек, что неприемлемо. Планировалось, что он должен выполняться порядка 20 мсек (50 Гц). А вот возникает еще вопрос: 640*480*2 байт памяти для 640x480, как минимум, используется, что равно 600Кб. Если верить ti, то самое бодрое, что есть - TMS320DM642-720 c 256 KB внутренней памяти. Это получается, что во внешней памяти данные хранятся или я не понимаю всего? Далее, 720e6/640/480/50 = 46.875. То есть, для 640x480x50 раз/сек есть, в лучшем случае, 46 тактов. Реально - еще меньше. Однозначно, работать нужно из внутренней памяти, причем не просто из внутренней памяти, а еще и так, чтобы данные укладывались в кэш первого уровня, иначе, грубо говоря, время выполнения увеличится чуть ли не в два раза. Таким образом необходимо: 1. Создать во внутреней памяти буфера для хранения трех строк: 1.1. Текущая строка 1.2. Предыдущая строка. 1.3. Следующая строка. 2. Настроить канал ДМА, чтобы во время обработки буферов (1.2.) и (1.1.) копировались данные из внешней памяти в (1.3.). 3. Дожидаемся окончания работы ДМА, свопим буфера и запускаем снова канал ДМА, а сами тем временем обрабатываем предыдущие строки. И, думаю, если копнуть глубже, то окажется, что времени не 1/50 секунды есть, а 1/25, не так ли? Реально частота кадров какая? Здесь надо менять очень серьезно все. А уже потом - оптимизировать код, там тоже есть, где разгуляться.
|
|
|
|
Сообщений в этой теме
Degun Лишние NOP в ассемблерном коде Oct 23 2007, 11:54  fontp Цитата(Degun @ Oct 23 2007, 16:15) А разв... Oct 23 2007, 12:28     fontp Неприятный какой алгоритм, сплошные условные опера... Oct 26 2007, 12:40      Degun Как известно у TI C6000-го семейства 8 конвейеров.... Oct 30 2007, 20:12       Edmundo Цитата(Degun @ Oct 30 2007, 23:12) Как из... Oct 30 2007, 20:32        Degun Цитата(Edmundo @ Oct 30 2007, 23:32) Куча... Oct 31 2007, 06:29         fontp Цитата(Degun @ Oct 31 2007, 09:29) Если ц... Oct 31 2007, 08:42          Degun Цитата(fontp @ Oct 31 2007, 11:42) Ну, он... Oct 31 2007, 19:50           fontp Цитата(Degun @ Oct 31 2007, 22:50) А есть... Oct 31 2007, 20:20            Degun Цитата(fontp @ Oct 31 2007, 23:20) Короче... Nov 7 2007, 19:59             fontp Цитата(Degun @ Nov 7 2007, 22:59) Что-то ... Nov 8 2007, 07:33             vadkudr Цитата(Degun @ Nov 8 2007, 04:59) Что-то ... Nov 20 2007, 13:33             SIA Цитата(Degun @ Nov 7 2007, 22:59) Что-то ... Mar 17 2008, 17:09       qxov Цитата(Degun @ Nov 16 2007, 16:08) Задача... Nov 16 2007, 21:53        Degun Цитата(qxov @ Nov 17 2007, 00:53) Вот пло... Nov 17 2007, 10:54        qxov Как успехи? Вот, набросал на коленке кусочек. Може... Nov 19 2007, 20:42        Degun Цитата(qxov @ Nov 17 2007, 00:53) Вот так... Nov 20 2007, 17:38 mdmitry Возможно оффтор! В MATLAB ImageProcessing Tool... Nov 18 2007, 11:09 Degun Уважаемый qxov я сделал вашу функцию calcModes с п... Nov 22 2007, 14:13 qxov Цитата(Degun @ Nov 22 2007, 17:13) Уважае... Nov 22 2007, 14:49 qxov А можно ли считать, что за пределами кадра есть ра... Nov 22 2007, 20:00 Degun Цитата(qxov @ Nov 22 2007, 23:00) А можно... Nov 23 2007, 11:58  qxov Цитата(Degun @ Nov 23 2007, 14:58) Да впо... Nov 23 2007, 12:50   Degun Цитата(qxov @ Nov 23 2007, 15:50) Точно 7... Nov 25 2007, 17:44    qxov Цитата(Degun @ Nov 25 2007, 20:44) Точно ... Nov 26 2007, 07:41     Degun Цитата(qxov @ Nov 26 2007, 10:41) Я в DSP... Nov 26 2007, 12:19 qxov Не знаю, на сколько этот вариант подходит:
если m... Nov 26 2007, 19:07 Degun Цитата(qxov @ Nov 26 2007, 22:07) Не знаю... Nov 27 2007, 12:26  qxov Цитата(Degun @ Nov 27 2007, 15:26) Вообще... Nov 28 2007, 06:07   Degun Цитата(qxov @ Nov 28 2007, 09:07) Начинат... Dec 6 2007, 17:40    qxov Цитата(Degun @ Dec 6 2007, 20:40) Такие с... Dec 7 2007, 06:20     Degun Вот такой у меня получился код для DSP. Но для изо... Feb 1 2008, 12:43 Николай Z Цитата(Degun @ Oct 23 2007, 14:54) Code C... Dec 6 2007, 23:23 qxov Очень тяжелый вложенный цикл. Нужно рассмотреть во... Feb 13 2008, 10:16 Degun Цитата(qxov @ Feb 13 2008, 13:16) Очень т... Feb 19 2008, 12:55 Degun Следующий вариант выполняется на 1 мсек быстрее, ч... Mar 17 2008, 13:29
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|