Сортировка массива блоков

Автор Тема: Сортировка массива блоков  (Прочитано 4351 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
 Имеется массив однотипных AcDbBlockReference с атрибутом,
которому присваевается номер, в зависимости от позиции AcDbBlockReference

Код - C++ [Выбрать]
  1. #include <omp.h>
  2. #include <fstream>
  3. using std::ios_base;
  4. using std::ofstream;
  5. ofstream fi;
  6. AcDbObjectIdArray ids;
  7.  
  8. void Bsort() {
  9.  
  10.     if (prompt()) {
  11.         fi.open("bsort.txt", ios_base::app);
  12.         fi << "\nМассив" << ids.length() << "шт";
  13.         double t0 = omp_get_wtime();
  14.  
  15.         if (filterBlockRef()) {
  16.  
  17.             fi << "\nfilterBlockRef: " << omp_get_wtime() - t0;
  18.             double t1 = omp_get_wtime();
  19.  
  20.             sortBlockRef();
  21.  
  22.             fi << "\nsortBlockRef: " << omp_get_wtime() - t1;
  23.             t1 = omp_get_wtime();
  24.  
  25.             drawBlockAtt();
  26.  
  27.             fi << "\ndrawBlockAtt: " << omp_get_wtime() - t1;
  28.             fi << "\nОбщее время: " << omp_get_wtime() - t0;
  29.         }
  30.      fi.close();
  31.     }
  32. }
  33.  
  34. void drawBlockAtt() {
  35.     AcString tag;
  36.     AcDbAttribute *at;
  37.     int value = 1;
  38.     int len = ids.length();
  39.  
  40. #pragma omp parallel for schedule(static) shared(ids, value)\
  41.                 private(at) if(len > 2000)  // распаралеливание потоков вывода
  42.  
  43.     for (int i = 0; i < len; ++i) {
  44. #pragma omp critical  // отсутствие этой директивы приводит к критической ошибке
  45.         {
  46.             if (!acdbOpenObject(at, ids[i], kForWrite)) {
  47.                 at->setTextString(tag.format(_RXST("%d"), value++).kwszPtr());
  48.                 at->close();
  49.             }
  50.         }
  51.     }
  52. }
  53. //-------------------------------
  54. // Результат выполнения:
  55. //
  56. // Массив: 20000шт
  57. // filterBlockRef: 0.165681
  58. // sortBlockRef: 0.00592158
  59. // drawBlockAtt: 1.25335
  60. // Общее время: 1.4265
  61.  

Можно ли ускорить вывод (функция drawBlockAtt) отсортированных значений  атрибута (избавиться от критической секции #pragma omp critical или другим способом) ?
« Последнее редактирование: 12-08-2019, 16:25:45 от Sergey_K »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Сортировка массива блоков
« Ответ #1 : 12-08-2019, 15:41:02 »
Sergey_K,
ObjectARX не допускает параллельное обращение к большинству из своих API. И в первую очередь при работе с базой.
Можешь поэкпериментировать с транзакциями. При массовых изменениях в базе они должны работать быстрее.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Сортировка массива блоков
« Ответ #2 : 12-08-2019, 15:46:49 »
Допускает, если параллельные обращения не связанны с выделением и освобождением памяти и модификацией базы данных чертежа.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Сортировка массива блоков
« Ответ #3 : 12-08-2019, 15:50:32 »
Допускает, если параллельные обращения не связанны с выделением и освобождением памяти и модификацией базы данных чертежа.
Я написал то, что официально декларирует Autodesk.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Сортировка массива блоков
« Ответ #4 : 12-08-2019, 15:57:04 »
Вот такое работает параллельно:
Код - C++ [Выбрать]
  1. #pragma omp parallel for schedule(static) shared(ids, px, py, tag)\
  2.                     private(rf, ati, at, pt) if(len > 100)
  3.         for (int i = 0; i < len; ++i) {
  4.                 if (!acdbOpenObject(rf, ids[i])) {
  5. #pragma omp critical
  6.                         {
  7.                                 ati = rf->attributeIterator();
  8.                         }
  9.                         rf->close();
  10.                         if (ati) {
  11.                                 for (; !ati->done(); ati->step()) {
  12.                                         if (!acdbOpenObject(at, ati->objectId())) {
  13.                                                 if (!tag.compare(at->tagConst())) {
  14.                                                         ids[i] = at->id();
  15.                                                         pt = at->position().transformBy(matrix);
  16.                                                         at->close();
  17.                                                         px[i] = pt.x;
  18.                                                         py[i] = pt.y;
  19.                                                         break;
  20.                                                 }
  21.                                                 at->close();
  22.                                         }
  23.                                 }
  24. #pragma omp critical
  25.                                 {
  26.                                         delete ati;
  27.                                 }
  28.                         }
  29.                 }
  30.         }
  31.  

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Сортировка массива блоков
« Ответ #5 : 12-08-2019, 17:28:25 »
Можешь поэкпериментировать с транзакциями. При массовых изменениях в базе они должны работать быстрее.

Быстрее, но незначительно

Массив: 20000шт
filterBlockRef: 0.140452
sortBlockRef: 0.058506
drawBlockAtt: 1.07757
Общее время: 1.28226

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Сортировка массива блоков
« Ответ #6 : 12-08-2019, 21:23:40 »
Sergey_K,
Надеюсь это всё происходило в одной транзакции. Впрочем, изменение 20000 сложных объктов за одну-две секунды - это нормальная скорость для AutoCAD. Сильно сомневаюсь, что можно что-то здесь ускорить.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Сортировка массива блоков
« Ответ #7 : 12-08-2019, 21:44:46 »
Александр Ривилис,
в одной.
Похоже что более ускорять нечего.
Самая трудоёмкая операция (сортировка) оказалась самой короткой по времени....   ???

Фактически получается не то время что, вычисляет таймер, а раза в 2-2.5 дольше

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Сортировка массива блоков
« Ответ #8 : 12-08-2019, 21:47:49 »
Самая трудоёмкая операция (сортировка) оказалась самой короткой по времени....   

Тебе кажется, что она самая трудоёмкая. Ты же не знаешь что делает AutoCAD при операциях модификации примитивов...
Ну и надеюсь, что ты проверял в Release, а не в Debug.
« Последнее редактирование: 12-08-2019, 23:10:45 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Сортировка массива блоков
« Ответ #9 : 12-08-2019, 21:57:36 »
Александр Ривилис,
в релизе конечно.

Не тянет изменение значения атрибута на большую трудоёмкость, с разницей в сортировке 3 массивов (x, y, id) по времени в сотни раз...

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Сортировка массива блоков
« Ответ #10 : 12-08-2019, 22:16:12 »
Александр Ривилис,
в релизе конечно.

Не тянет изменение значения атрибута на большую трудоёмкость, с разницей в сортировке 3 массивов (x, y, id) по времени в сотни раз...
Там еще и файловые операции возникают при модификации базы, что резко уменьшает скорость. Кстати, можешь попробовать AcDbDatabase::disableUndoRecording()
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Сортировка массива блоков
« Ответ #11 : 13-08-2019, 10:35:52 »
Александр Ривилис,
отказываться от undo - не есть хорошо.

На 20000 disableUndoRecording() сокращает время вывода в БД на 30%
В данном случае массивы более 2000 встречаются крайне редко, а в диапазоне до 2000 время работы составляет до 0.15 сек, что удовлетворительно.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Сортировка массива блоков
« Ответ #12 : 13-08-2019, 10:39:22 »
отказываться от undo - не есть хорошо.
В общем случае  - да. Но, например, при пакетной обработке чертежей может помочь.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение