Jump to content

    
Sign in to follow this  
inventor

оптимизировать цикл

Recommended Posts

есть контроллер кортекс, подключенный к нему через FPGA дисплей

вывожу картинку старого формата XBM на экран монитора

DMAнет  и выводить нужно попиксельно

экран долго рисует, что ожидаемо

 

/**
 * Вывести файл XBM (ширина должна делиться на 8!!!)
 */
void bitmap_draw_xbm(const char* bmp, int width, int height)
{
    u32 k = 0;
    u8 m = 0, pix;

    for (int y = 0; y < height; y++) {
	for (int x = 0; x < width; x++) {
	    pix = bmp[k];
	    pix = (pix >> m) & 1;
	    display_put_pixel(x, DISPLAY_HEIGTH - y, pix == 0? 0xFFFF: 0);            

	    m++;
	    if (m == 8) {
		k++;
		m = 0;
	    }
	}
    }
}

            
        
    
    

формат XBM такой, если кто не знает:

#define x_width 512
#define x_height 512
static char x_bits[] = {
0x28, 0x8a, 0xe2, 0x3f, 0xfe, 0xf3,

каждый бит в байте и сдвигать

выводя попиксельно

Share this post


Link to post
Share on other sites

это я уже убрал и сделал так:

    for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x += 8, k++) {
        pix = *(bmp + k);

            p0 = pix & 1;
            p1 = pix & 2;            
            p2 = pix & 4;
            p3 = pix & 8;            

            p4 = pix & 16;
            p5 = pix & 32;            
            p6 = pix & 64;
            p7 = pix & 128;            
            
        display_put_pixel(x, DISPLAY_HEIGTH - y, p0 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 1, DISPLAY_HEIGTH - y, p1 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 2, DISPLAY_HEIGTH - y, p2 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 3, DISPLAY_HEIGTH - y, p3 == 0? 0xFFFF: 0);            

        display_put_pixel(x + 4, DISPLAY_HEIGTH - y, p4 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 5, DISPLAY_HEIGTH - y, p5 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 6, DISPLAY_HEIGTH - y, p6 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 7, DISPLAY_HEIGTH - y, p7 == 0? 0xFFFF: 0);            
    }
    }

но все равно скорость не достаточная

Share this post


Link to post
Share on other sites
30 minutes ago, inventor said:

это я уже убрал и сделал так:


    for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x += 8, k++) {
        pix = *(bmp + k);

            p0 = pix & 1;
            p1 = pix & 2;            
            p2 = pix & 4;
            p3 = pix & 8;            

            p4 = pix & 16;
            p5 = pix & 32;            
            p6 = pix & 64;
            p7 = pix & 128;            
            
        display_put_pixel(x, DISPLAY_HEIGTH - y, p0 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 1, DISPLAY_HEIGTH - y, p1 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 2, DISPLAY_HEIGTH - y, p2 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 3, DISPLAY_HEIGTH - y, p3 == 0? 0xFFFF: 0);            

        display_put_pixel(x + 4, DISPLAY_HEIGTH - y, p4 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 5, DISPLAY_HEIGTH - y, p5 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 6, DISPLAY_HEIGTH - y, p6 == 0? 0xFFFF: 0);            
        display_put_pixel(x + 7, DISPLAY_HEIGTH - y, p7 == 0? 0xFFFF: 0);            
    }
    }

но все равно скорость не достаточная

основное время тратится скорее всего вот тут

display_put_pixel

можно посмотреть как это реализовано и как то оптимизировать. например выводить не по 1 точке а сразу 8

 

Share this post


Link to post
Share on other sites
Just now, Zeal0t said:

можно посмотреть как это реализовано и как то оптимизировать. например выводить не по 1 точке а сразу 8

 

это просто запись в память

    (*((volatile u32 *) (addr))) = col;

вероятно сама плис долго выводит

решили сделать 2 адресных пространства

1-е попиксельное рисование в цветах

2-е вывожу двойное слово где каждый бит- ч/б пиксель

так будет быстрее работать

Share this post


Link to post
Share on other sites
2 часа назад, inventor сказал:

экран долго рисует, что ожидаемо

А что такое display_put_pixel() - предлагаете телепатам угадать? Очередная угадайка....

Share this post


Link to post
Share on other sites

Восемь раз display_put_pixel вызывается и каждый раз аргумент вычисляется (DISPLAY_HEIGTH - y): есть гарантия что не 8 раз одно и то же? Из цикла по x - долой...

Share this post


Link to post
Share on other sites
22 minutes ago, inventor said:

   (*((volatile u32 *) (addr))) = col;

Зачем volatile?
 

pix = *bmp++;

*outpix++ = (pix & 1) ? 0xFFFF : 0;
*outpix++ = (pix & 2) ? 0xFFFF : 0;
*outpix++ = (pix & 4) ? 0xFFFF : 0;
*outpix++ = (pix & 8) ? 0xFFFF : 0;
*outpix++ = (pix & 16) ? 0xFFFF : 0;
*outpix++ = (pix & 32) ? 0xFFFF : 0;
*outpix++ = (pix & 64) ? 0xFFFF : 0;
*outpix++ = (pix & 128) ? 0xFFFF : 0;

 

Share this post


Link to post
Share on other sites
2 часа назад, amaora сказал:

Зачем volatile?

А зачем такая куча условных выражений? Ведь каждое - это ветвление, а значит особенные тормоза.

Цитата

 


pix = *bmp++;

*outpix++ = (pix & 1) ? 0xFFFF : 0;
*outpix++ = (pix & 2) ? 0xFFFF : 0;
*outpix++ = (pix & 4) ? 0xFFFF : 0;
*outpix++ = (pix & 8) ? 0xFFFF : 0;
*outpix++ = (pix & 16) ? 0xFFFF : 0;
*outpix++ = (pix & 32) ? 0xFFFF : 0;
*outpix++ = (pix & 64) ? 0xFFFF : 0;
*outpix++ = (pix & 128) ? 0xFFFF : 0;

 

ТС как будто сделал целью сделать как можно более тормозной код. Только такое объяснение нахожу этой куче лишних переменных и ветвлений...  :russian_ru:

Да и у ТСа вроде при бите==0 должно получаться 0xFFFF, а у Вас - наоборот.

Если у ТСа внутри этого секретного макроса display_put_pixel() (и макроса ли?) действительно именно такие записи в память, то всё делается много лаконичнее и быстрее:

int i = ~*bmp++;
*outpix++ = i << 31 >> 31 & 0xFFFF;
*outpix++ = i << 30 >> 31 & 0xFFFF;
*outpix++ = i << 29 >> 31 & 0xFFFF;
...  

При полной оптимизации это должно дать всего по 3 ассемблерных команды на каждый бит.

А вообще низкоуровневая оптимизация делается низкоуровневыми средствами - ассемблером. Так можно сделать ещё оптимальнее.

 

PS: А дальше надо смотреть - а зачем 32-битные записи, если старшие 16 бит содержимого памяти всегда ==0? Может хватит 16-битных записей? И, если внешняя шина к FPGA у ТСа 16-разрядная, то это может дать существенный прирост скорости.

Вобщем - при таком уровне информации, когда ТС 90% данных утаил трудно что-то насоветовать разумное...  :unknw:

Share this post


Link to post
Share on other sites

Самый быстрый способ могу предложить только такой:

	SBFX   R1,R0,#0,#1
	STRH   R1,[R2,#0]   
	SBFX   R1,R0,#1,#1
	STRH   R1,[R2,#2]
	....
	SBFX   R1,R0,#7,#1
	STRH   R1,[R2,#14]
	

По два такта на пиксель.

Это вполне и при помощи GCC inline asm делается, так что можно обойтись без отдельного модуля на ассемблере.

Edited by Rst7

Share this post


Link to post
Share on other sites
4 минуты назад, jcxz сказал:

А зачем такая куча условных выражений? Ведь каждое - это ветвление, а значит особенные тормоза.

Я дополню. Если процессорный конвейер равен 6-ти, то каждое ветвление, т.е. вызов или возврат - это 6 тактов ожидания. В этом плане проще сделать 6 команд последовательно, чем одно ветвление. Ну и тут надо смотреть, есть ли команды не "перехода по условию", а "пропуска команды по условию"... Потому как пропуск команды - это только один такт, а не 6...

А вот дальше надо смотреть, как именно производится запись в экранную память. Если запись возможно только на обратном ходе луча, то можно посчитать, сколько циклов записи туда влезет. И возможно, что быстрее будет подсинхронизироваться с этим процессом - на прямом ходе луча вычислять, а на обратном быстро, быстро писать в экранную память...

Share this post


Link to post
Share on other sites
13 минут назад, Rst7 сказал:

Самый быстрый способ могу предложить только такой:

По два такта на пиксель.

Это так можно только если действительно можно не записывать старшие 16 бит. Я выше уже писал об этом.

Share this post


Link to post
Share on other sites
29 minutes ago, jcxz said:

Это так можно только если действительно можно не записывать старшие 16 бит. Я выше уже писал об этом.

Я так думаю, что если сдуру там и сделано 32 бита только, то можно писать не 0 и 0xFFFF, а 0 и 0xFFFFFFFF почти наверняка.

Share this post


Link to post
Share on other sites
13 hours ago, jcxz said:

А что такое display_put_pixel() - предлагаете телепатам угадать? Очередная угадайка....

/**
 * Вывод пикселя на экран с координатами x, y и с заданым цветом
 */
IDEF void display_put_pixel(u16 x, u16 y, u16 col)
{
    volatile u32 addr;


    if (x < DISPLAY_WIDTH && y < DISPLAY_HEIGTH) {

    /* расчитаем координаты точки */
    addr = DISPLAY_START_ADDR + (((DISPLAY_HEIGTH - y - 1) * DISPLAY_WIDTH + x) << 2);

    /* Выведем точку */
    *((u32 *) (addr)) = col;
//      printf("%d, %d; ", x, y);
    }
}

IDEF это static inline

13 hours ago, Obam said:

Восемь раз display_put_pixel вызывается и каждый раз аргумент вычисляется (DISPLAY_HEIGTH - y): есть гарантия что не 8 раз одно и то же? Из цикла по x - долой...

убрал 

        u16 h = DISPLAY_HEIGTH - y;    

Share this post


Link to post
Share on other sites
2 часа назад, inventor сказал:

    if (x < DISPLAY_WIDTH && y < DISPLAY_HEIGTH) {

    /* расчитаем координаты точки */
    addr = DISPLAY_START_ADDR + (((DISPLAY_HEIGTH - y - 1) * DISPLAY_WIDTH + x) << 2);

    /* Выведем точку */
    *((u32 *) (addr)) = col;
//      printf("%d, %d; ", x, y);
    }

 

Да уж... Вы действительно сделали всё, чтобы затормозить работу как можно сильнее...  :hang1:

13 часов назад, Rst7 сказал:

Я так думаю, что если сдуру там и сделано 32 бита только, то можно писать не 0 и 0xFFFF, а 0 и 0xFFFFFFFF почти наверняка.

Глядя на код ТС-а, там можно ожидать чего угодно.  :russian_ru:

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this