Добрый день.
Мы используем Gis Designer версии 11.10.7 под Astra Linux SE 1.4. Среда разработки Qt Creator.
Столкнулись со следующей проблемой. При использовании функций mapGetHeightValue или mapGetHeightArray в не основном потоке часто происходит зависание
потока, либо в последствии возникают наведенные ошибки (Вроде повисания процесса отрисовки карты). При чтении рельефа мы используем мьютексы.
Причем, если теже самые действия выполнять в основном потоке (Где отрисовывается GUI-интерфейс), то все нормально.
Урезали нашу задачу до маленького примера, где подобные глюки возникают всегда, даже если все выполнять все в одном, но не основном потоке. Карта масштаба 1 : 50000 и состоит из 350 листов.
Матрица высот расчитана с дискретом в 50 м. Если не вызыватть функцию mapGetHeightValue, то глюки пропадают.
В связи с этим вопрос: Как осуществлять параллельное считывание рельефа? Поддерживает ли функция mapGetHeightArray работу в множестве потоков?
Прилагаю пример кода:
Заголовочный файл calcMap.h:
Файл calcMap.cpp:
Мы используем Gis Designer версии 11.10.7 под Astra Linux SE 1.4. Среда разработки Qt Creator.
Столкнулись со следующей проблемой. При использовании функций mapGetHeightValue или mapGetHeightArray в не основном потоке часто происходит зависание
потока, либо в последствии возникают наведенные ошибки (Вроде повисания процесса отрисовки карты). При чтении рельефа мы используем мьютексы.
Причем, если теже самые действия выполнять в основном потоке (Где отрисовывается GUI-интерфейс), то все нормально.
Урезали нашу задачу до маленького примера, где подобные глюки возникают всегда, даже если все выполнять все в одном, но не основном потоке. Карта масштаба 1 : 50000 и состоит из 350 листов.
Матрица высот расчитана с дискретом в 50 м. Если не вызыватть функцию mapGetHeightValue, то глюки пропадают.
В связи с этим вопрос: Как осуществлять параллельное считывание рельефа? Поддерживает ли функция mapGetHeightArray работу в множестве потоков?
Прилагаю пример кода:
Заголовочный файл calcMap.h:
Код |
---|
#include <QApplication> #include <QVector> #include <QList> #include <QRunnable> #include <QThread> #include <QMutex> #include <ma th.h> #include <QDebug> #ifndef MAP_API_H #include <mapapi.h> #endif using namespace std; class informVyr { private: public: informVyr() {} ~informVyr() {} QMutex *hMut_ptr; QString pathToMap; HMAP hmap; double Xstart; // Координаты начала матрицы double Ystart; double dsk; // дискрет QVector <QVector <double> > masIfo; void testVyr(int numL, int kolL); }; // Класс расчета class calcMap { private: public: calcMap(QString Mappath); ~calcMap(); informVyr MIV; }; // Класс параллельной обработки class parInf : public QThread { private: informVyr *MIV; int numL; // Номер среза int kolL; // кол-во срезов public: parInf(informVyr *MIV, int numL, int kolL); void run(); }; |
Файл calcMap.cpp:
Код |
---|
#include "calcMap.h" calcMap::calcMap(QString Mappath) { QMutex infMut; MIV.hMut_ptr = &infMut; MIV.pathToMap = Mappath; // Путь к карте MIV.hmap = mapOpenMap(Mappath.toStdString().c_str(), GENERIC_READ); if (!MIV.hmap) return; // Путь к матрице высот (Должна лежать в каталоге с картой и иметь такое же имя) string pathMtw = Mappath.toStdString(); pathMtw = pathMtw.substr(0, pathMtw.length()-4); pathMtw += ".mtw"; qDebug() << "\nПодключение матрицы высот"; if (!mapOpenMtrForMap( MIV.hmap, pathMtw.c_str(), GENERIC_READ)) return; double dsk = 4000; // Дискрет // Расчет кол-ва элементов матрицы int cou = mapGetMtrCount(MIV.hmap); MTRDESCRIBE desc; mapGetMtrDescribe(MIV.hmap, 1, &desc); // Граничные точки матрицы double X1 = desc.FrameMeters.X1; double Y1 = desc.FrameMeters.Y1; double X2 = desc.FrameMeters.X2; double Y2 = desc.FrameMeters.Y2; for (int i = 2; i <= cou; i++) { mapGetMtrDescribe(MIV.hmap, i, &desc); if (desc.FrameMeters.X1 < X1) X1 = desc.FrameMeters.X1; if (desc.FrameMeters.Y1 < Y1) Y1 = desc.FrameMeters.Y1; if (desc.FrameMeters.X2 > X2) X2 = desc.FrameMeters.X2; if (desc.FrameMeters.Y2 > Y2) Y2 = desc.FrameMeters.Y2; } int xCou = ceil((X2 - X1)/dsk); int yCou = ceil((Y2 - Y1)/dsk); X2 = X1 + xCou*dsk; Y2 = Y1 + yCou*dsk; qDebug() << "\nМатрица:" << xCou << yCou; // Формирование матрицы MIV.masIfo.clear(); MIV.masIfo.resize(xCou); for (int i=0 ; i < xCou; i++) { MIV.masIfo[i].resize(yCou); for (int j=0; j < yCou; j++) MIV.masIfo[i][j] = 0; // Зануление } // Инициализация параметров MIV.Xstart = X1; MIV.Ystart = Y1; MIV.dsk = dsk; int kolL = QThread::idealThreadCount(); // Кол-во параллельных процессов if (kolL < 1) kolL = 1; bool ParalPro = true; // Признак распараллеливания kolL = 1; // Принудительная установка 1 потока qDebug() << "Кол-во процессов" << kolL; if (!ParalPro) { qDebug() << "\nПоследовательный расчет"; for (int i = 0; i < kolL; i++) MIV.testVyr(i, kolL); } else { qDebug() << "\nПараллельный расчет по линиям"; // Массив обрабатывющих потоков QVector <parInf*> masThread; masThread.resize(kolL); // Создание потоков for (int i = 0; i < kolL; i++) masThread[i] = new parInf(&MIV, i, kolL); // Запуск потоков for (int i = 0; i < kolL; i++) masThread[i]->start(); int activeTCou = kolL; // Ожидание завершения всех потоков while (activeTCou > 0) { activeTCou = 0; for (int i = 0; i < kolL; i++) // Подсчет текущих потоков if (masThread[i]->isRunning()) activeTCou++; } // Удаление потоков for (int i = 0; i < kolL; i++) { delete masThread[i]; } } mapCloseMap(MIV.hmap); // Закрытие карты return; } calcMap::~calcMap() { } // Распараллеливание parInf::parInf(informVyr *MIV, int numL, int kolL) : QThread() { this->MIV = MIV; this->numL = numL; this->kolL = kolL;; } void parInf::run() { MIV->testVyr(numL, kolL); } void informVyr::testVyr(int numL, int kolL) { qDebug() << "\nНачало расчета среза линий №" << numL; int begL = 0; int endL = masIfo.size(); if (numL != -1) { // Если задан номер среза begL = numL*masIfo.size()/kolL; endL = (numL+1)*masIfo.size()/kolL; if (numL == kolL-1) // Если срез последний endL = masIfo.size(); // Конец массива } qDebug() << "От" << begL << " До" << endL; for (int i = begL; i < endL; i++) { if (i%5 == 0) qDebug() << "i = " << i; for (int j = 0; j < masIfo[i].size(); j++) { hMut_ptr->lock(); mapGetHeightValue(hmap, Xstart + dsk*i, Ystart + dsk*j); hMut_ptr->unlock(); } } qDebug() << "\nКонец расчета среза линий" << numL; return; } |