10816
|
Qt / Общие вопросы / Re: Параллельные вычисления (проблемы)
|
: Декабрь 10, 2009, 13:27
|
Добрый день Подсобрал статистику http://www.2shared.com/file/9869897/e1de3de1/stat.html (к сожалению, прикрепить здесь не удается). Запущены 4 нитки. Для каждой точки выполняется N расчетов (первая колонка таблицы). Расчеты могут быть более или менее трудоемкие (таблицы 1, 2 и 3) в зависимости от объема исходных данных. В таблицах представлены худшие (для меня) варианты. Когда 1000 вычислений на точку и/или каждый расчет трудоемок - все хорошо, наступает эффект "в разы". А вот когда вычислений маловато - проблемы. В таблицах указано время (в секундах) и коэффициент выигрыша (по отношению к версии где все выполняется в главной нитке). Столбцы "job = " показывают размер "пачки", т.е. порцию вычислений для каждой нитки. На первый взгляд (из общих соображений) чем больше пачка - тем лучше. Но на деле совсем не так. Чего-то важного я здесь не понимаю. Может быть, поизучать исходники OpenMP - других идей пока нет.
|
|
|
10817
|
Qt / Общие вопросы / Re: Потоки (прервать или продолжить)
|
: Декабрь 10, 2009, 11:45
|
Страшная функция - не оптимизирована страшно, краткая характеристика. Думаю как упрастить. Что можна заменить на более быстродействующее?Смысл работы: передаю список выделений итемов, составляю список выделенных колонок и строк; по этому списку формирую список итемов для сортировки, сортирую полученный список и устанавливаю эти итемы в выделенные колонки/строки. Списков много, как уменьшить. Преимущество такой сортировки ячеек для таблицы - могу сортировать разные колонки, находящиеся не рядом (поэтому и список выделений selectionRange) и могу выделять ячейки с помощью Ctrl , недостатки для колонки 10000 итемов сортирует долго Кто чем может помогите? 10 тысяч итемов - для сортировки не объем, если Вы сортируете грамотно это должно выполняться за доли секунды. Для начала проверьте что все списки/контейнеры подаются по ссылке. Не поможет - выкладывайте Вашу "страшную ф-цию", будем смотреть.
|
|
|
10818
|
Qt / Общие вопросы / Re: Потоки (прервать или продолжить)
|
: Декабрь 10, 2009, 01:13
|
У меня в конце той страшной функции вызывается функция somethingChanged(), которая тоже долго вычисляется. Как тогда быть в таком случае с прогресс диалогом (проверкой на отмену)? Ну например ещё qSort... UpdateProgress(progress, i)
Ну и подайте ей progress (QProgressDialog) как аргумент, напр. опишите ее так bool somethingChanged( QProgressDialog & progress );
// вызов if (!somethingChanged(progress)) return false;
А внутри ф-ции работайте в том же стиле, заряжайте индикатор и все дела. Насчет сортировки - да, это не обновит индикатор, ну так что с того - не все операции могут быть прерваны, это нормально. И вообще, что это за философия такая "страшная ф-ция" и.т.п? Это они должны Вас бояться а не Вы их
|
|
|
10819
|
Qt / Общие вопросы / Re: Потоки (прервать или продолжить)
|
: Декабрь 09, 2009, 23:00
|
Как по мне надо сделать маленькие изменения C++ (Qt) if ((row+1 ) % UPDATE_STEP) return false; if (UpdateProgress(progress, it)) return false; каждую проверку заменить
Почему нет? Но тогда измените название - не UpdateProgress, а, например, UserCancel. И еще: не прессуйте текст типа (row+1) - это выглядит как зажатый зародыш в утробе матери Что Вам, пробелов жалко? Пишите со вкусом, покажите всем что Вы хотели сказать, не жмитесь к стенке
|
|
|
10820
|
Qt / Общие вопросы / Re: Параллельные вычисления (проблемы)
|
: Декабрь 09, 2009, 16:05
|
2 BREНа его картинке, показанно 223 потока Надеюсь что его потоков много меньше Если же его потоков большенство, то тут в серьез стОит задуматься над другим алгоритмом. Это просто Activity Monitor показывает все threads в системе. Я предлагаю пользователю ввести число ниток, по умолчанию = числу процессоров. То есть в данном случае - всего 4. (+главная) Igors, а ты не смотрел в сторону OpenMP? Конечно, если есть такая возможность.
Возможность есть, у XCode это даже 1 из опций компилятора (правда не знаю про Вындоуз). Почему не смотрю - не понимаю как он может здесь помочь, я вижу какие места не могут быть распараллелены. Базовый механизм один для всех (может я неправ)
|
|
|
10821
|
Qt / Общие вопросы / Re: Параллельные вычисления (проблемы)
|
: Декабрь 09, 2009, 14:41
|
Мои мысли по данному вопросу складываются из двух твоих тем: про GetPixel и потокобезопастностm простых операций.... Может я и ошибаюсь.... Мне кажется, что такое поведение складывается из-за того, что сами задачи, которые выполняют нити ничтожны по сравнению с оверхедом от использования методов синхронизации. Т.е. если нить, грубо говоря, делает пару умножений и пару сложений и при этом использует операции синхронизации (тот же mutex), то ты больше времени тратишь на переключения контекста и ожидание, чем на сами вычисления. Думаю по этому и однопоточная версия выполняется быстрее. Наверное лучше нагружать нити посильнее, например обрабатывать не по одному пикселю, а массивами пикселей. Играясь с размерами массивов, можно будет подбирать оптимальную нагрузку на ядра. Кстати, я уже предлагал такое решение в теме про GetPixel.
Ну если бы можно было все разбить на N независимых кусков и дать каждой нитке по куску - я бы с удовольствием так и сделал. Как говорил классик "съесть конечно он бы съел да только кто ж ему даст?" Многие (самые трудоемкие) данные пикселей интерполируются, зависят друг от друга. Простой пример: есть квадрат из пикселей, напр. 4х4. Посчитали углы, посмотрели разброс значений. Достаточно мал - отлично, пошли дальше. Нет - разбиваем на 4 суб-квадрата и парим каждый. Расчет данных одного пикселя совсем не сводится к вычислению текстур (картинок) - это просто фрагмент расчета который должен быть thread-safe. Для каждого пикселя производится 200 и более расчетов (выбросов лучей). Они-то и потребляют 95% (и более) всего времени. Вот я и делаю чтобы эти 200 выполнялись в разных нитках. Понимаю что др. подходы также возможны, но каждый имеет свои минусы. Например, разбив все пиксели на какие-то "большие квадраты/полосы" я получу головную боль с их "сшивкой". Плюс эти квадраты могут требовать совершенно разных вычислений. Разумеется, расчеты объединены в "пачки" и я могу варьировать ее размер. Трудоемкость одного пикселя: 80К пикселей рассчитываются за 32 сек (1 процессор). Общие ресурсы - для простоты скажем "отсутсвуют". Диаграмма нагрузки (4 нитки) здесь http://www.2shared.com/file/9838740/b1147927/Picture_2.html
|
|
|
10822
|
Qt / Общие вопросы / Re: QPainter::drawPixmap - похоже конкретный Баг?
|
: Декабрь 09, 2009, 13:24
|
Я так понял 2 painter'а (Painter и painter). Первый рисует в pixmap, второй ее выводит. Если так то интересно проверить: C++ (Qt) QPixmap Pixmap(10, 10); if (1) { QPainter Painter(Pixmap); Painter.fillRect(Pixmap.rect(), Qt::green); // GREEN 10*10 Painter.fillRect(QRect(0,0,1,10), Qt::red); // RED 1*10 + GREEN 9*10 } painter.drawPixmap(QRect(1,0,9,10), *pixmap, QRect(0,0,9,10)); // QT BUG
|
|
|
10823
|
Qt / Общие вопросы / Re: Параллельные вычисления (проблемы)
|
: Декабрь 08, 2009, 23:45
|
Какая там общая память (shared memory) в задаче и для семафор? Один промах в cache (memory-miss) стоит очень много вычислений! Эрудиция моя такая: на семафорах он ждёт страницу из общей или дальней памяти, а все вычисления происходят в презагруженных регистрах или презагруженной cache. То есть, критическая роль в данном случае - это скорость памяти а не процессора. Понял, отвечаю. Shared memory в задаче есть но для тестирования полностью отключена. Все происходит в памяти процесса. Были проверены 3 варианта семафоров (OSX) 1) sem_open (BSD named semaphore) 2) semaphore_create (POSIX семафор если не путаю) 3) QSemaphore (Qt) 1 и 2 дают тот же результат, 3 немного слабее - но общая картина та же.
|
|
|
10824
|
Qt / Общие вопросы / Параллельные вычисления (проблемы)
|
: Декабрь 08, 2009, 21:45
|
Добрый вечер
Занимаюсь задействованием всех процессоров для долгих вычислений и столкнулся с проблемой. Процессор Intel Xeon (2 процессора по 2 ядра). Сделал механизм для ниток, семафоры - все необходимое. Результаты получаются такие:
1) Подставляю "тестовые расчеты" (т.е. проверяю сам механизм). Результаты разумные: на 4-х нитках время более чем в 2 раза меньше (по сравнению с начальной "безниточной" версией) . Понимаю что не все распараллелено, да что-то еще съедят семафоры, так что нормально.
2) Подставляю "рабочие расчеты" (как они в задаче). Результат - время на 4-х нитках даже несколько БОЛЬШЕ исходного. Хотя все вычисления выполняются правильно, результаты совпадают. В чем дело? Смотрю в tools (OSX). CPU Sampler (по простому говоря профайлер) показывает - время ожидания на семафорах резко возросло. Activity Monitor показывает - значительная часть процессорного времени была съедена системой - непонятно для чего.
Но самое забавное - при использовании профайлера/tools время становится .. заметно меньше! (на 25% как минимум). Перепроверил много раз.
Понимаю что "нужно смотреть расчеты". Ну это сотни файлов и привести их здесь нет возможности. Да и что смотреть? Разумеется я все упростил как мог: отключил I/O, все вызовы OC и.т.п. Но эффект остается.
Идеи, опыт, эрудиция?
Спасибо
|
|
|
10825
|
Qt / Общие вопросы / Re: Потоки (прервать или продолжить)
|
: Декабрь 08, 2009, 15:04
|
Can you read or only write? Вам говорили что диалог должен быть модальным? Просто слушайте и понимайте - и массы вопросов не возникнет. Не надо ничего разбивать, просто заряжайте индикатор для каждой операции, например #define UPDATE_STEP 100
bool UpdateProgress( QProgressDialog & progress, int row ) { if ((row + 1) % UPDATE_STEP) return true; // update once per UPDATE_STEP progress.setValue(row); // calls processEvents for modal dialog return progress.wasCanceled(); }
bool Spreadsheet::sort_data( const QList<QTableWidgetSelectionRange> & range, const SpreadsheetCompare & compare ) { if(range.isEmpty()) return false;
QProgressDialog progress(this); progess.setModal(true); // should be modal // check range progress.setLabelText(tr("Checking range")); progress.setMaximum(range.size()); for (int it = 0; it < range.size(); it++) { if (range[it].leftColumn() < 0) return false; if (range[it].bottomRow() < 0) return false; if (range[it].rightColumn() < 0) return false; if (range[it].topRow() < 0) return false; if (!UpdateProgress(progress, it)) return false; }
// fill columns QList<int> columns; QList<int> rows_n; progress.setLabelText(tr("Adding rows & columns")); progress.setMaximum(range.size()); progress.setValue(0); for(int i = 0; i < range.size(); i++) { for (int col = range[i].leftColumn(); col <= range[i].rightColumn(); col++) if (columns.indexOf(col) == -1) columns.push_back(col); for(int row = range[i].topRow(); row <= range[i].bottomRow(); row++) if (rows_n.indexOf(row) == -1) rows_n.push_back(row); if (!UpdateProgress(progress, i)) return false; } // sort progress.setLabelText(tr("Sorting")); progress.setMaximum(2); progress.setValue(0); qSort(columns.begin(), columns.end()); qSort(rows_n.begin(), rows_n.end());
// add progress.setLabelText(tr("Adding rows & columns")); progress.setMaximum(rows_n.size()); progress.setValue(0); QList<QStringList> rows; for(int i = 0; i < rows_n.size(); i++) { if (!UpdateProgress(progress, i)) return false; QStringList row; for (int j = 0; j < columns.size(); j++) { if (is_item_in_list_selection_range(range, rows_n[i], columns[j])) { if (isError_in_cell(rows_n[i], columns[j])) return false; if (item(rows_n[i], columns[j])) row.push_back(text(rows_n[i], columns[j])); } } if (row.size() == columns.size() && row.size() > 0) rows.push_back(row); else { rows_n.removeOne(rows_n[i]); i--; } row.clear(); } QList<QStringList> temp = rows; qStableSort(rows.begin(), rows.end(), compare); if (rows == temp) return false;
// set items progress.setLabelText(tr("Setting Items")); progress.setMaximum(rows.size()); progress.setValue(0); for (int i = 0; i < rows.size(); i++) { if (!UpdateProgress(progress, i)) return false; for(int j = 0; j < rows[i].size(); j++) setItem(rows_n[i], columns[j], rows[i][j]); } return true; }
|
|
|
10826
|
Qt / Общие вопросы / Re: Потоки (прервать или продолжить)
|
: Декабрь 07, 2009, 22:19
|
Можна как-то обойтись именно в функции без прогрессдиалога и светить после выполнения части задачи сигналом value А в функции, которая вызвала этот слот сделать connect с этим сигналом value и соединить с прогрессдиалогом на вывод текущего прогресса. Но тут проблема как прервать работу той страшной функции в слоте с коннектом.
Зачем "обходиться" без вещи которая делает именно то что Вам нужно? QProgressDialog уже "светит", просто давайте ему setProgress (см. ссылку) Как распределить показание прогрессдиалога? Может условно поделить свою функции на проценты выполнения
Объявите в начале ф-ции QProgressDialog progress. К каждому processEvents в Ваших ф-циях добавьте: progress.setProgress(it); .. qApp->processEvents(); if (progress.wasCanceled()) { return false; }
Сделайте это, потом задавайте очередные вопросы (если они возникнут).
|
|
|
10827
|
Qt / Общие вопросы / Re: Потоки (прервать или продолжить)
|
: Декабрь 07, 2009, 21:39
|
Это две самые страшные функции одна вызывает другую (запускаю слот sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range) (1 из функций) из mainWindow) Спасибо за ссылку, хорошо для одного цикла в функции, а как быть с разными операциями в функции
Задача изначально была такова- выполняется функция (долгая операция), если пользователь запускает на выполнение другую операцию выводится сообщение: "Прервать или продолжить?", тоже самое и при закрытии окна при выполнении задачи. При подтверждении прерывания желательно было бы откатить то, что сделала функция (не обязательно), а так прервать выполнение функции; продолжить - продолжение выполнение той задачи. Заранее большое спасибо, хочу сделать просто хорошее приложение (обработать все возможные нюансы).
Объясните ЗАЧЕМ Вы даете пользователю возможность что-то нажимать если текущая операция не закончена? Все гораздо проще, не придумывайте себе проблем. Началась трудоемкая операция - покажите индикатор QProgressDialog. А поскольку он модальный (см. ссылку) то единственное что пользователь может сделать - нажать cancel и Вы легко это можете отловить (см. ту же ссылку). Все остальное будет зажато модальностью индикатора. Надо переспросить пользователя - не проблема, породитесь от QProgressDialog. Надо откатить операцию - у Вас все на руках, одно удовольствие. Не лезьте в асинхронку, потом полжизни на аптеку будете работать
|
|
|
10828
|
Программирование / С/C++ / Re: как ограничить float?
|
: Декабрь 07, 2009, 12:54
|
qreal V=0.01*floor(100*(Vol)+0.5); Не попрет с отрицательными числами А вообще navrocky прав: с round покороче будет - не знал что есть такая удобная ф-ция, спасибо. Не жирно ли будет для хранения данных? Люди 16-битный float используют вовсю...
|
|
|
10829
|
Компиляторы и платформы / Mac OS X / Re: Leopard не могу найти make
|
: Декабрь 07, 2009, 11:34
|
Я ничего нигде не прописывал. Стоял XCode 3.1. Скачал qt-sdk-mac....dmg, запустил инсталлер, выбрал тот же раздел (системный) где XCode. Все поставилось, qmake запускается. Есть проблемы с XCode но то уже др. вопрос, а так ходит.
|
|
|
10830
|
Qt / Общие вопросы / Re: Потоки (прервать или продолжить)
|
: Декабрь 07, 2009, 10:56
|
Изначально вопрос был Как на момент выполнения трудоемкой задачи заблокировать сигналы от кнопок, закрытие окна.....?
Это решается несколькими способами, например очень хорошо смотрится QProgressDialog. Вот старая но хорошая ссылочка http://www.opennet.ru/docs/RUS/qt3_prog/x4064.htmldaimon, все что Вам нужно это переписать текст из примера (или выложите ф-цию, я добавлю текст). Это займет 5 минут и совершенно незачем вдаваться в нюансы потоков и.т.п. Это не имеет к Вашей задаче никакого отношения.
|
|
|
|
|