Russian Qt Forum
Ноябрь 23, 2024, 00:26 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: рендеринг 5 000 000 точек с перерисовкой  (Прочитано 7814 раз)
lenovo2014
Гость
« : Декабрь 04, 2014, 07:20 »

всем привет. у меня такая задача возникла: нужно выводить около 5 мильонов точек , с последующей частой перерисовкой ( 500 мс - 1 с) . Одна точка - это ячейка из матрицы, которая выводится на экран по градации яркости.
Сейчас я отрисовываю это во QGraphivsView в drawBackground():
Код:
void view_iko::drawBackground(QPainter *painter, const QRectF &rect)
{
        painter->fillRect(q,Qt::transparent);
        int h,s,l,a;
        base_color.getHsl(&h,&s,&l,&a);
        QColor color = base_color;
        for(int i=0; i<5000; i++){
            for (int j=0; j< 1000; j++)
        {

                a = mw->var->matrixAmpl2[i][j] * 255 / 2000 ;
                color.setAlpha(a);
                painter->setPen(QPen(color,1));
                x=(scl)*sin(i*0.003067962);
                y=(scl)*cos(i*0.003067962);
                painter->drawPoint(cP.x()+x,cP.y()-y);
        
            }
        }

    }
    QGraphicsView::drawBackground(painter, rect);

}
все это дело тормозит. посоветуйте как получше решить эту задачку ?
upd: вывод идет в realtime; фильтровать информацию нельзя
« Последнее редактирование: Декабрь 05, 2014, 11:08 от lenovo2014 » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #1 : Декабрь 04, 2014, 07:47 »

Лучше формировать самому все точки в памяти QImage, а потом готовую картинку рисовать на экране.
И я бы посчитал сразу две таблицы по синусу и косинусу для всех возможных значений индекса от 0 до 999.
« Последнее редактирование: Декабрь 04, 2014, 08:09 от Old » Записан
lenovo2014
Гость
« Ответ #2 : Декабрь 05, 2014, 11:04 »

попытался сделать как Вы сказали:
в отдельном потоке:
Код:
void draw::run(){
    exec(); // поток в ожидании
}
сигналю на отрисовку
Код:
 void draw::draw_signal(){

        draw1(); // рисую в pixmap1 значения из матрицы
        mw->var->lock_drawing_2->lock();
        *mw->var->p2 = *mw->var->p1; // копирую в pixmap2
        mw->var->lock_drawing_2->unlock();
}
в gui-потоке:
Код:
void view_iko::drawBackground(QPainter *painter, const QRectF &rect)//drawBackground(QPainter *painter, const QRectF &rect)
{


    drawGrid(); // рисую сетку и прочие мелочи
    mw->var->lock_drawing_2->lock();
    painter->drawPixmap(q,*mw->var->p2); // вывожу буфер на экран
    mw->var->lock_drawing_2->unlock();
    QGraphicsView::drawBackground(painter, rect);

}
все равно тормозит, в том плане, что функция drawBackground() выполняется с задержкой, равной времени отрисовки в буфер №1 в отдельном потоке, при чем функции drawPixmap и *mw->var->p2 = *mw->var->p1 выполняются моментально и на скорость не влияют. Тогда, почему draw1() тормозит все приложение, ведь я специально вынес в отдельный поток эту функцию? Где ошибка у меня подскажите пожалуйста!
« Последнее редактирование: Декабрь 05, 2014, 11:09 от lenovo2014 » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Декабрь 05, 2014, 11:18 »

От того что вынесли в отдельный поток ничего особо не меняется, это имело бы смысл для разгрузки главного. Надо рисовать на QImage причем напрямую (см QImage::bits) и предрассчитать синус и косинус.

Хоть бы во внешний цикл их вынесли, они зависят только от i, зачем молотить 1000 раз в цикле по j ?
« Последнее редактирование: Декабрь 05, 2014, 11:21 от Igors » Записан
lenovo2014
Гость
« Ответ #4 : Декабрь 05, 2014, 11:27 »

От того что вынесли в отдельный поток ничего особо не меняется, это имело бы смысл для разгрузки главного.
Хоть бы во внешний цикл их вынесли, они зависят только от i, зачем молотить 1000 раз в цикле по j ?
Идея такая была: разгрузить gui-поток, чтобы в нем рисовалось то, что занимает мало времени : сетка и pixmap2; А то, что занимает много времени, т.е. pixmap1, готовился бы в отдельном потоке.

Для синусов уже создал таблицу, спасибо.
Записан
ieroglif
Гость
« Ответ #5 : Декабрь 05, 2014, 11:35 »

Igors +1
логика стара как OpenGL =) (а скорее всего ещё старше)
1. Всё что можно расчитать заранее (син-кос) - расчитываем заранее. В процессе уже используем готовые расчитанные таблицы/вектора/хэши/что_подойдёт_по_индексации_и_будет_максимально_быстро.
2. Сигнал на перерисовку должен инициировать отдельный тред, в котором будет пересоздаваться буфферная картинка.
2.1. т.е. есть ДВА буфферных qimage/qpixmap/.... - один "рабочий", один "буфферный" - в другом треде
2.2. сигнал инициирует перерисовку в буфферном треде
2.3. основной тред ВСЕГДА рисует из "рабочего" буфера
2.4. когда тред отработал и готов новый буфер - он выдаёт сигнал, по которому "рабочий" и "буфферный" картинки меняются местами/данными/...
Записан
lenovo2014
Гость
« Ответ #6 : Декабрь 05, 2014, 11:46 »

Igors +1
логика стара как OpenGL =) (а скорее всего ещё старше)
1. Всё что можно расчитать заранее (син-кос) - расчитываем заранее. В процессе уже используем готовые расчитанные таблицы/вектора/хэши/что_подойдёт_по_индексации_и_будет_максимально_быстро.
2. Сигнал на перерисовку должен инициировать отдельный тред, в котором будет пересоздаваться буфферная картинка.
2.1. т.е. есть ДВА буфферных qimage/qpixmap/.... - один "рабочий", один "буфферный" - в другом треде
2.2. сигнал инициирует перерисовку в буфферном треде
2.3. основной тред ВСЕГДА рисует из "рабочего" буфера
2.4. когда тред отработал и готов новый буфер - он выдаёт сигнал, по которому "рабочий" и "буфферный" картинки меняются местами/данными/...
я так пробовал, когда pixmap1 и pixmap2 чередуются и готовятся в отдельном потоке, все равно задержка ровно на столько, сколько занимает отрисовка данных.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Декабрь 05, 2014, 11:48 »

Идея такая была: разгрузить gui-поток, чтобы в нем рисовалось то, что занимает мало времени : сетка и pixmap2; А то, что занимает много времени, т.е. pixmap1, готовился бы в отдельном потоке.
Так от этого рисование pixmap1 никак не ускоряется, а она и является узким местом. Вообще неоднократно замечал что "потоки" лепятся везде, где надо и не надо Улыбающийся Сделайте расчеты аккуратно, может и 1 ядра достаточно
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #8 : Декабрь 05, 2014, 11:57 »

попытался сделать как Вы сказали:
Я говорил про другое.
Вы представляете как устроенная картинка изнутри? Как она хранится в памяти?
Я вам предложил формировать эту картинку "руками", модифицируя напрямую память + сделать предварительный расчет.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #9 : Декабрь 05, 2014, 12:02 »

я так пробовал, когда pixmap1 и pixmap2 чередуются и готовятся в отдельном потоке, все равно задержка ровно на столько, сколько занимает отрисовка данных.
А нечего для таких вещей использовать QPixmap.
Коли возникают вопросы с производительностью, в первую очередь не мешало посмотреть какое хранилище используется и оценить все его плюсы и минусы.
И как минимум прочитать описание
Цитата: assistant
Qt provides four classes for handling image data: QImage, QPixmap, QBitmap and QPicture. QImage is designed and optimized for I/O, and for direct pixel access and manipulation, while QPixmap is designed and optimized for showing images on screen. QBitmap is only a convenience class that inherits QPixmap, ensuring a depth of 1. The isQBitmap() function returns true if a QPixmap object is really a bitmap, otherwise returns false. Finally, the QPicture class is a paint device that records and replays QPainter commands.
и сделать вывод, что для таких целей QPixmap ну никак не подходит.
Я здесь, наверное, уже в сотый раз повторяю, что пиксмапы хранятся на стороне сервера.
Так вот, чтобы в пиксмапе нарисовать один пиксель нужно сформировать соответствующий запрос, отослать его серверу и дождаться от него ответа.
Т.е. всё делается синхронно. По крайней мере так происходит на X11.
Записан

Qt 5.11/4.8.7 (X11/Win)
lenovo2014
Гость
« Ответ #10 : Декабрь 05, 2014, 12:16 »

попытался сделать как Вы сказали:
Я говорил про другое.
Вы представляете как устроенная картинка изнутри? Как она хранится в памяти?
Я вам предложил формировать эту картинку "руками", модифицируя напрямую память + сделать предварительный расчет.

ок, пробую сделать как выше описали через bits(). где  расположить код отрисовки, в обработчике drawBackground() ?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Декабрь 05, 2014, 12:40 »

Я здесь, наверное, уже в сотый раз повторяю, что пиксмапы хранятся на стороне сервера.
Так вот, чтобы в пиксмапе нарисовать один пиксель нужно сформировать соответствующий запрос, отослать его серверу и дождаться от него ответа.
Несомненно если оптимизировать рисование - то QImage (а не что-то другое). Но мне кажется Вы перегибаете палку. Кто такой мифический "сервер"? Улыбающийся По-моему QPixMap - это, грубо говоря, хранение имеджа в формате OC. Напр CGBitmapRef в OSX или HBITMAP в Вындоуз (в иксах не знаю). Он может быть как-то упакован или нет - это личное дело ОС. Рисовать на нем можно, это не смертельно, но такое рисование может оказаться значительно медленнее чем рисование на экране (старая легенда что "кеш быстрее" не катит), т.к. контекст рисования растровый. Здесь сильно зависит от OC. Напр на OSX векторный контекст в неск раз (если не на порядок) быстрее растрового (наверное пасется в OpenGL а тот тюкает по пикселям).

Хотя здесь это ничего не меняет, однозначно нужно заполнять пиксели самому в QImage, быстрее этого ничего не будет.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #12 : Декабрь 05, 2014, 13:05 »

Но мне кажется Вы перегибаете палку. Кто такой мифический "сервер"? Улыбающийся
В случае обычного X Window System display server (Xserver), который используется на всех unix-ах,
если не задействован X Rendering Extension, именно так и есть как я описал.

По-моему QPixMap - это, грубо говоря, хранение имеджа в формате OC.
Не в формате ОС, а графической подсистемы и хранение в её памяти, а не клиентского приложения.
« Последнее редактирование: Декабрь 05, 2014, 13:09 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Декабрь 05, 2014, 13:35 »

Не в формате ОС, а графической подсистемы и хранение в её памяти, а не клиентского приложения.
Это скорее спор о терминах. Напр HBITMAP вряд ли хранится на видео. Да, формально приложение имеет handle - но память/ресурсы все равно расходуются (клиентская или нет - не суть). Где ОС хранит - его дело, главное что формат закрыт, прямого доступа к пыкселям нет, хотя можно рисовать создав контекст.
Записан
lenovo2014
Гость
« Ответ #14 : Декабрь 05, 2014, 20:45 »

всем большое спасибо, сделал через QImage::scanline()
дополнительно помог вот этот пост http://www.prog.org.ru/topic_20274_0.html
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.09 секунд. Запросов: 23.