Qt: Лучший способ реализовать "осциллографическую" графику в реальном времени - PullRequest
6 голосов
/ 03 октября 2010

Я работаю над Gui-модулем для Qt для построения измерений в реальном времени, как в цифровом осциллографе, на основе Qwt .Все работает так, как и должно, но, возможно, осталось добавить некоторые функции; -)

В данный момент данные хранятся по столбцам в QVectors вместе с одним глобальным QReector timeReference в одном отдельном QObject.Таким образом, данные могут быть отброшены построчно, чтобы сохранить только измерения в определенном прошлом.Все QVectors всегда имеют одинаковую длину.Затем полные данные можно выстроить в QwtPlot по строкам и по времени.

Я хочу больше инкапсулировать хранилище данных, чтобы быть более независимым от работы с измерениями.Поэтому было бы неплохо добавить отдельный список временных координат для каждого измерения и поместить их оба в отдельный объект QObject, который принимает и доставляет данные.Тогда было бы 10 или 20 таких объектов QObject, по одному на каждый канал данных, которые отдельно наносятся перекрывающим QObject на QwtPlot.

Теперь данные могут быть динамически какими угодно - как данные хранятся, измененные или выброшенные между ними не должны быть видны снаружи.

Мой вопрос: это умный?20 или 30 объектов QO, содержащих каждые 10000 измерений, 10000 значений времени, а также отдельную область памяти аналогичного размера (динамически заполненную), где подмножество данных представлено для построения ...?Разумно ли принимать каждое измерение в своем объекте QObject в качестве сигнала с частотой около 1 кГц?Часть сигнал / слот основана на идее сделать каждый объект QThread позже и реализовать фильтрацию данных в реальном времени, например, нижний проход или БПФ, - поэтому соединения сигнал / слот удобны для управления выходом вмногопоточная среда?

Как эффективно хранить данные внутри моих объектов OB?Я думаю о двух QList, один для времени и один для ценных данных.Затем выделение двух простых двойных массивов на лету для динамического доступа, чьи указатели вместе с длиной помещаются в структуру и возвращаются методом accessData (pastTime).Динамическая память заполняется комбинациями timeVal / измерения от «сейчас» до определенной точки в прошлом, устанавливаемой сигналом.Все хрупкое, защищенное мьютексами внутри объекта QObject.

При отбрасывании старых значений необходимо искать в QList с самого начала первое значение, которое достаточно молодо, чтобы его сохранить, те, которые находятся перед этим индексом, выбрасываются,Является ли QMap умнее благодаря своей функции upperBound ()?Я полагаю, что скрытые накладные расходы не будут стоить.

Как один профессионал попытается решить эту проблему красиво, эффективно или без каких-либо хлопот?Специальные Qt-особенности, о которых я должен знать?Или есть даже бесплатные решения?Во всяком случае, много текста для такого основного вопроса ... Спасибо, что прочитали здесь; -)

Заранее спасибо

Марвин

Эдит: сделал некоторые очистки в аргументациипосле стайнс комментариев.

Ответы [ 2 ]

6 голосов
/ 04 октября 2010

Ответ photo_tom в значительной степени подводит итог: я бы держался подальше от QObjects для реализации обработки и обработки данных.

  • Если вы когда-нибудь решите использовать что-то другое, кроме Qt, для вашего графического интерфейса, вам будет гораздо сложнее реорганизовать код. Такие классы, как QList и QVector, можно без особых проблем заменить на аналоги STL, но часть сигнал / слот - это нечто другое.
  • любая реализация третьей части для обработки сигналов, такая как фильтрация / fft, вероятно, будет принимать необработанные указатели на 1D или 2D данные, поэтому вам придется извлечь их из QVector, что, я даже не уверен, возможно. Если это не так, вам придется вытащить каждый семпл из QVector и скопировать его в блок памяти, затем обработать, а затем поместить его обратно в QVector.
  • , что приводит нас к вашему вопросу о QList / QMap: это можно сделать с любым из них, но они фактически спроектированы как динамические контейнеры с итераторами произвольного доступа, в то время как у вас есть куски памяти фиксированного размера, содержащие 2D-данные. Возможно, стоит поискать собственный класс контейнера данных, который точно соответствует вашим потребностям. Возьмите документ, запишите, что вам действительно нужно, очистите свой разум и забудьте о Qt / STL / ... затем подумайте, какие компоненты вам понадобятся для реализации этого, затем идите дальше и подумайте, как эти компоненты могут быть реализованы ( в конце концов с точки зрения Qt).
  • для такого кода лучше не перераспределять, никогда. Заранее установите ограничения на максимальную историю и количество выборок, которые вы собираетесь разрешить (или сделайте это параметром конфигурации), и выделите необходимые массивы в начале программы, повторно используя ту же память в дальнейшем.
  • рассмотрим кольцевой буфер. Это удобно, когда данные поступают с другой скоростью, чем они извлекаются (как это обычно происходит со сбором данных), они не требуют перераспределения, они автоматически сохраняют историю и могут быть реализованы с минимальным количеством копий памяти, если они читаются / Методы записи возвращают указатели непосредственно в основную память.
  • возможно, переосмыслите идею потока, это может сделать ваш код излишне сложным: в конце концов, все данные из разных каналов должны попасть на экран одновременно. Если пользователь просматривает данные из канала 1 в момент времени x, данные из канала 2 также должны быть получены из времени x, иначе это не имеет большого смысла как область. Но предположим, что вы обрабатываете данные из этих каналов в разных потоках, вам нужна дополнительная синхронизация в потоке, который выполняет фактическое отображение, поскольку не все потоки данных завершат обработку блоков в момент времени x одновременно. Кроме того, учтите, что прирост производительности может вообще не произойти: если процессор должен рассчитывать FFT для 30 каналов и клипов на 100%, действительно ли он будет быстрее вычислять эти FFT, если они разделены на 30 потоков?
  • Кстати, вы говорите, что это основной вопрос, я думаю, что на самом деле это не так. Я сделал несколько приложений для сбора / обработки / визуализации / сохранения данных на разных устройствах, и я считаю, что эти приложения ему сложнее всего разрабатывать ..
3 голосов
/ 03 октября 2010

QObjects кажутся на первый взгляд отличным способом решения проблем хранения данных такого типа.Я думал о том же, когда впервые начал использовать Qt.Однако это не то, для чего они предназначены.Есть хорошая запись о том, что на самом деле QObjects и делают на http://www.informit.com/articles/article.aspx?p=667415.

Если все, что вы собираетесь сделать, это сохранить данные в классе, как я прочитал ваш вопрос, то не используйте классы на основе QObject,Накладные расходы серьезно повредят вашей работе.

Что касается конкретных возможностей Qt, то нет ничего особенного, что могло бы помочь Qt.Я обнаружил, что контейнеры Qt намного проще в использовании, чем стандартная библиотека шаблонов или некоторые из специализированных библиотек boost, потому что в то время я не знал достаточно хорошо.

Мое лучшее предложение с точки зрения производительностизаключается в минимизации количества новых / удалений путем записи системы пула памяти или использования Boost Pool для каждого нового чтения.А также свести к минимуму перемещение данных на всех.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...