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

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

Страниц: [1] 2 3 ... 5   Вниз
  Печать  
Автор Тема: Тормоза в Qt IO  (Прочитано 36973 раз)
romank
Гость
« : Июль 27, 2009, 07:53 »

Почему не Windows95? Улыбающийся
Сейчас переписываю свой проект под qt. Заметил черезвычайное падение производительности при I/O операциях.  После перехода на unsafe скорость обработки файлов (~1Gb) достигла 2 секунд.
Под Qt я пока болтаюсь на уровне 8-10 секунд. В форумах советуют начать проецировать в память.
.net быстрее работает со считыванием файлов?

P.S. Вообще надо было мне завести отдельную нитку, но и так по поводу i/o было много написано.
Записан
Rcus
Гость
« Ответ #1 : Июль 27, 2009, 08:06 »

Крутая у вас I/O подсистема, у меня винты на линейном чтении дают всего примерно 100МиБ/с
« Последнее редактирование: Июль 27, 2009, 08:08 от Rcus » Записан
romank
Гость
« Ответ #2 : Июль 27, 2009, 09:01 »

Да, действительно.
Хотел сказать про то что файлы могут достигать объема ~1Gb.
Далее читать: 2 секунды на 110Mb в .net и 8 секунд в Qt.
Записан
Rcus
Гость
« Ответ #3 : Июль 27, 2009, 09:09 »

Все равно не верю в такую разницу. Без графа профайлера утверждать ничего не могу, но помоему дело в не реализации I/O подсистемы Qt, а в алгоритмах обработки.
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #4 : Июль 27, 2009, 10:18 »

Насчет windows 98 и 2000 - много работаю на научные организации.
Виндоус им покупать очень дорого да и нафига.

по поводу файлов - если памяти много, то мапим файл в память и обрабатываем.
Записан
romank
Гость
« Ответ #5 : Июль 27, 2009, 11:47 »

Специфика моей (формально научной) работы связана с рабочими станциями.
Программа которую я пишу 100% будет использоватся на не слабых машинах под XP.
Для портирования с .NET
(причины: обработка больших массивов данных, полагал что openGL на Qt будет быстрее [но сегодня вижу что реализация отрисовки в QGLWiget оставляет желать лучшего, низкий FPS, сражаюсь из последних сил, дай мне сил волшебный бубен])

переписывал основной код, суть которого считывать последовательно Int32 и Float из бинарного файла. В .net реализации ввел следующее (это уже последние этапы оптимизации, после которых скорострельность показалась мне достаточной):

Код
C#
       unsafe void ReadSingleBuffer(float[] s_buffer)
       {
           int count = s_buffer.Length * 4;
           byte[] m_buffer = new byte[count];
           br.Read(m_buffer, 0, count);
 
           //convert byte -> single
           for (int i = 0; i < s_buffer.Length; ++i)
           {
               uint num = (uint)(((m_buffer[0 + i * 4] | (m_buffer[1 + i * 4] << 8)) | (m_buffer[2 + i * 4] << 0x10)) | (m_buffer[3 + i * 4] << 0x18));
               s_buffer[i] = *(((float*)&num));
           }
       }
 

Здесь всё просто, читаю четыре байта и через указатель "обзываю" float`ом. Также для Int.
Вот кусочек кода в котором используются вызовы:

Код
C#
               br = new BinaryReader(fs, System.Text.Encoding.GetEncoding(1251))
...
               br.ReadBytes(54);
 
               this.progHeader1 = ReadString(75);
               this.progHeader2 = ReadString(75);
 
               br.ReadBytes(12);
 
               ReadInt32Buffer(numb);
 
               nx = numb[43];
               ny = numb[44];
               nz = numb[45];
 
               br.ReadBytes(12);
 

То есть большое количество мелких считываний до 100 байт за раз.

В Qt переписал практически также:
Код
C++ (Qt)
void DataLoader::readFloatbuffer(QFile &f, float*  f_buffer, int len)
{
char m_buffer[len * 4];
f.read(m_buffer, len * 4);
for (int i = 0; i < len; ++i)
f_buffer[i] = *(float*)(&m_buffer[i * 4]);
}
 

Использование:
Код
C++ (Qt)
QFile file(fname);
file.open(QIODevice::ReadOnly);
...
file.read(54);
progHeader1 = readString(file, 75);
progHeader2 = readString(file, 75);
 
file.read(12);
readInt32buffer(file, numb, 100);
 
nx = numb[43];
ny = numb[44];
nz = numb[45];
 
file.read(12);
 

Провал в производительности. При первом вызове черезвычайно медленно (как-то неэффективно работает буфферирование чтоли), потом вроде нормально. Пробовал считывать большие куски и разбирать их в памяти. Прироста заметного не получил. Мапить в память можно, но даст ли это мне достаточного ускорения? Может как-то меньшей кровью можно обойтись?
Записан
BRE
Гость
« Ответ #6 : Июль 27, 2009, 12:06 »

А для чего читать в один буфер, а затем перекладывать во второй?
Можно же просто:
Код
C++ (Qt)
void DataLoader::readFloatbuffer(QFile &f, float*  f_buffer, int len)
{
f.read( (char*)f_buffer, len * sizeof( *f_buffer ) );
}
 
Записан
romank
Гость
« Ответ #7 : Июль 27, 2009, 12:17 »

Отличный совет, мне не хватает ещё моего знания cpp.
Меня сбило с толку что падение производительности отмечалось при первом запуске. Теперь всё хорошо.
Буду дальше бороться за opengl.

UPD:
Подскажите, как сделать проще следующее:
Код
C++ (Qt)
float GLView::readFloat(QFile &f)
{
char m_buffer[4];
f.read(m_buffer, 4);
return *((float*)m_buffer);
}
 

UPD: Забыл добавить, основной причиной перехода на Qt стало отличное GUI.
« Последнее редактирование: Июль 27, 2009, 12:23 от romank » Записан
spectre71
Гость
« Ответ #8 : Июль 27, 2009, 12:49 »

Отличный совет, мне не хватает ещё моего знания cpp.
Меня сбило с толку что падение производительности отмечалось при первом запуске. Теперь всё хорошо.
Буду дальше бороться за opengl.

UPD:
Подскажите, как сделать проще следующее:
Код
C++ (Qt)
float GLView::readFloat(QFile &f)
{
char m_buffer[4];
f.read(m_buffer, 4);
return *((float*)m_buffer);
}
 

UPD: Забыл добавить, основной причиной перехода на Qt стало отличное GUI.




Код
C++ (Qt)
float GLView::readFloat(QFile &f)
{
float val;
f.read((char*)&val, sizeof(val));
return val;
}

никогда не пиши так:
char m_buffer[4];
пиши только так:
char m_buffer[sizeof(float)];

Записан
romank
Гость
« Ответ #9 : Июль 29, 2009, 10:45 »

Да, поспешил радоватся, всё осталось также.
Подскажите какие есть профайлеры под Qt?
Записан
BRE
Гость
« Ответ #10 : Июль 29, 2009, 10:58 »

Да, поспешил радоватся, всё осталось также.

Меня сбило с толку что падение производительности отмечалось при первом запуске. Теперь всё хорошо.
Думаю, что это происходит из-за того, что при первом запуске файл реально читается с диска, при последующих запусках этот файл храниться в дисковом кэше и данные с диска не читаются.
Можно попробовать использовать буферизацию при чтении, т.е. читать большими кусками, а разбор данных делать из оперативной памяти.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #11 : Июль 29, 2009, 12:35 »

Подскажите какие есть профайлеры под Qt?

Глянь вот этот топик http://www.prog.org.ru/topic_2196_0.html
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Winstrol
Гость
« Ответ #12 : Июль 29, 2009, 13:10 »

Подскажите, как сделать проще следующее:
Код
C++ (Qt)
float GLView::readFloat(QFile &f)
{
char m_buffer[4];
f.read(m_buffer, 4);
return *((float*)m_buffer);
}
 
Самое логичное так:
Код
C++ (Qt)
void GLView::readFloat(QFile &f,float& x)
{
f.read(&x, 4);
}
 
Но читать по 1 float'у из файла идея плохая.
Записан
romank
Гость
« Ответ #13 : Июль 29, 2009, 14:27 »

Под .net ещё пробовал читать полностью в память, потом разбирать - медленно и большие затраты памяти (весь файл мне не нужен).
Выйгрышный вариант оказался читать, пропускать. Я бы с радостью и не читал по одному float, но надо делать пропуски.
Пробовал и через seek, накладно на небольших отступах.

Посмотрел в src: read читывает в 4kb буффер.
Как можно отказатся от буферирования?

Про оптимизацию читал до вопроса ветку. В итоге под win не нашел бесплатного решения. Может мне и не нужен профайлер? Хочется (макимально) какие участки кода наиболее затратны? (минимально) Сделать самому замеры. Какой аналог StopWatch есть в Qt?
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #14 : Июль 29, 2009, 14:57 »

Сделать самому замеры. Какой аналог StopWatch есть в Qt?

Можешь использовать qDebug() + QTime::start\elapsed
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Страниц: [1] 2 3 ... 5   Вверх
  Печать  
 
Перейти в:  


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