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

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

Страниц: 1 2 [3]   Вниз
  Печать  
Автор Тема: Соглашения по стилю написания кода в Qt  (Прочитано 23037 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #30 : Январь 29, 2010, 14:33 »

Спс, а что насчет п. №1 ?
Записан

ArchLinux x86_64 / Win10 64 bit
SABROG
Гость
« Ответ #31 : Январь 29, 2010, 17:02 »

Спс, а что насчет п. №1 ?

Ничего. Судя по исходникам Qt у них даже нет единого стиля объявления типа переменных, иногда "int *", иногда "int* " (QObject *, QObject*, int&, int & и т.д.)

Провел бенчмарк циклов с вариантами:

Код
C++ (Qt)
#include <stdio.h>
 
#define NUM_ITERATION 2000000000
 
void ipostinc()
{
   volatile int a = 0;
   for (int i = 0; i < NUM_ITERATION; i++) {
       a = i;
   }
}
 
void ipreinc()
{
   volatile int a = 0;
   for (int i = 0; i < NUM_ITERATION; ++i) {
       a = i;
   }
}
 
void iadd()
{
   volatile int a = 0;
   for (int i = 0; i < NUM_ITERATION; i += 1) {
       a = i;
   }
}
 
void iregpostinc()
{
   volatile int a = 0;
   for (register int i = 0; i < NUM_ITERATION; i++) {
       a = i;
   }
}
 
void iregpreinc()
{
   volatile int a = 0;
   for (register int i = 0; i < NUM_ITERATION; ++i) {
       a = i;
   }
}
 
void iregadd()
{
   volatile int a = 0;
   for (register int i = 0; i < NUM_ITERATION; i += 1) {
       a = i;
   }
}
 
int main (int argc, char* argv[])
{
   ipostinc();
   ipreinc();
   iadd();
   iregpostinc();
   iregpreinc();
   iregadd();
   return 0;
}
 
 

Код:
g++ -g -pg -Wall -O3 -fno-inline main.cpp

Дале прошелся профайлером gprof.

Код:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name   
 16.67      0.86     0.86        1   860.00   860.00  iregpreinc()
 16.67      1.72     0.86        1   860.00   860.00  iregpostinc()
 16.67      2.58     0.86        1   860.00   860.00  iadd()
 16.67      3.44     0.86        1   860.00   860.00  ipreinc()
 16.67      4.30     0.86        1   860.00   860.00  iregadd()
 16.67      5.16     0.86        1   860.00   860.00  ipostinc()

Программа выполнялась 5.16 секунд.

Теперь уменьшаем переменную NUM_ITERATION до 1500000000:

Код:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name   
 16.80      0.65     0.65        1   650.00   650.00  iregpreinc()
 16.80      1.30     0.65        1   650.00   650.00  iadd()
 16.80      1.95     0.65        1   650.00   650.00  ipostinc()
 16.54      2.59     0.64        1   640.00   640.00  iregpostinc()
 16.54      3.23     0.64        1   640.00   640.00  ipreinc()
 16.54      3.87     0.64        1   640.00   640.00  iregadd()

Теперь уменьшаем переменную NUM_ITERATION до 1000000000:

Код:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name   
 16.92      0.44     0.44        1   440.00   440.00  ipreinc()
 16.92      0.88     0.44        1   440.00   440.00  ipostinc()
 16.54      1.31     0.43        1   430.00   430.00  iregpreinc()
 16.54      1.74     0.43        1   430.00   430.00  iregpostinc()
 16.54      2.17     0.43        1   430.00   430.00  iadd()
 16.54      2.60     0.43        1   430.00   430.00  iregadd()

Уменьшаем до 100 млн-ов:

Код:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name   
 19.23      0.05     0.05        1    50.00    50.00  iadd()
 19.23      0.10     0.05        1    50.00    50.00  ipostinc()
 15.38      0.14     0.04        1    40.00    40.00  iregpreinc()
 15.38      0.18     0.04        1    40.00    40.00  iregpostinc()
 15.38      0.22     0.04        1    40.00    40.00  ipreinc()
 15.38      0.26     0.04        1    40.00    40.00  iregadd()

Если брать три последних теста (где есть отличия), то во всех них лидируют 2 функции:

iregpostinc():
Код
C++ (Qt)
for (register int i = 0; i < NUM_ITERATION; i++) {
 

iregadd()
Код
C++ (Qt)
for (register int i = 0; i < NUM_ITERATION; i += 1) {
 

Если брать варианты без register, то в первом тесте все три варианта выполняются одно и то же время, в следующем тесте ipreinc() быстрее iadd() и ipostinc(), в другом тесте iadd() быстрее чем ipreinc() и ipostinc(). И в последнем тесте лидирует ipreinc(). Если разделить результаты по баллам, то получается такая картина:

ipreinc() - 3
iadd() - 2
ipostinc() - 1

В итоге можно сказать, что использование конструкции ++i предпочтительней, но нет никакой гарантии того, что она сделает цикл быстрее, может даже замедлить. Поэтому прежде чем бездумно делать оптимизацию лучше пройтись профайлером.
Записан
Rcus
Гость
« Ответ #32 : Январь 29, 2010, 17:45 »

А вы пробовали в objdump -S заглядывать? Я немного усложнил тест чтобы компилятор не смог заоптимизировать все до noop, для всех вариантов получился один и тот же код на платформе x86_64:
Код:
void iregadd()             
{                         
    for (register int i = 0; i < NUM_ITERATION; i += 1) {
  4005f0:       8b 15 3e 0a 20 00       mov    0x200a3e(%rip),%edx        # 601034 <argnn>
  4005f6:       85 d2                   test   %edx,%edx                                 
  4005f8:       7e 13                   jle    40060d <iregadd+0x1d>                     
  4005fa:       31 c0                   xor    %eax,%eax                                 
  4005fc:       0f 1f 40 00             nopl   0x0(%rax)                                 
        a = i;                                                                           
  400600:       89 05 2a 0a 20 00       mov    %eax,0x200a2a(%rip)        # 601030 <a>   
    }                                                                                     
}                                                                                         
                                                                                         
void iregadd()                                                                           
{                                                                                         
    for (register int i = 0; i < NUM_ITERATION; i += 1) {                                 
  400606:       83 c0 01                add    $0x1,%eax                                 
  400609:       39 d0                   cmp    %edx,%eax                                 
  40060b:       75 f3                   jne    400600 <iregadd+0x10>                     
  40060d:       f3 c3                   repz retq                                         
  40060f:       90                      nop                                               

0000000000400610 <main>:
        a = i;         
    }                   
}   
Но тест конечно непоказателен, вот с QHash::iterator еще было бы интересно Улыбающийся
Записан
SABROG
Гость
« Ответ #33 : Январь 29, 2010, 19:11 »

Похоже на то. Значит компилятору фиолетово какую конструкцию ты используешь, один хрен соптимизирует. Конечно хотелось бы увидеть другой тест, который мог бы быть показательным, но я не знаю как его сделать, нужен более опытный программист.

Код:
00000000 <__Z8ipostincv>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 10                sub    $0x10,%esp
   6:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%ebp)
   d:   31 c0                   xor    %eax,%eax
   f:   90                      nop
  10:   89 45 fc                mov    %eax,-0x4(%ebp)
  13:   40                      inc    %eax
  14:   3d 00 2f 68 59          cmp    $0x59682f00,%eax
  19:   75 f5                   jne    10 <__Z8ipostincv+0x10>
  1b:   c9                      leave
  1c:   c3                      ret
  1d:   8d 76 00                lea    0x0(%esi),%esi

00000020 <__Z7ipreincv>:
  20:   55                      push   %ebp
  21:   89 e5                   mov    %esp,%ebp
  23:   83 ec 10                sub    $0x10,%esp
  26:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%ebp)
  2d:   31 c0                   xor    %eax,%eax
  2f:   90                      nop
  30:   89 45 fc                mov    %eax,-0x4(%ebp)
  33:   40                      inc    %eax
  34:   3d 00 2f 68 59          cmp    $0x59682f00,%eax
  39:   75 f5                   jne    30 <__Z7ipreincv+0x10>
  3b:   c9                      leave
  3c:   c3                      ret
  3d:   8d 76 00                lea    0x0(%esi),%esi

00000040 <__Z4iaddv>:
  40:   55                      push   %ebp
  41:   89 e5                   mov    %esp,%ebp
  43:   83 ec 10                sub    $0x10,%esp
  46:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%ebp)
  4d:   31 c0                   xor    %eax,%eax
  4f:   90                      nop
  50:   89 45 fc                mov    %eax,-0x4(%ebp)
  53:   40                      inc    %eax
  54:   3d 00 2f 68 59          cmp    $0x59682f00,%eax
  59:   75 f5                   jne    50 <__Z4iaddv+0x10>
  5b:   c9                      leave
  5c:   c3                      ret
  5d:   8d 76 00                lea    0x0(%esi),%esi

00000060 <__Z11iregpostincv>:
  60:   55                      push   %ebp
  61:   89 e5                   mov    %esp,%ebp
  63:   83 ec 10                sub    $0x10,%esp
  66:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%ebp)
  6d:   31 c0                   xor    %eax,%eax
  6f:   90                      nop
  70:   89 45 fc                mov    %eax,-0x4(%ebp)
  73:   40                      inc    %eax
  74:   3d 00 2f 68 59          cmp    $0x59682f00,%eax
  79:   75 f5                   jne    70 <__Z11iregpostincv+0x10>
  7b:   c9                      leave
  7c:   c3                      ret
  7d:   8d 76 00                lea    0x0(%esi),%esi

00000080 <__Z10iregpreincv>:
  80:   55                      push   %ebp
  81:   89 e5                   mov    %esp,%ebp
  83:   83 ec 10                sub    $0x10,%esp
  86:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%ebp)
  8d:   31 c0                   xor    %eax,%eax
  8f:   90                      nop
  90:   89 45 fc                mov    %eax,-0x4(%ebp)
  93:   40                      inc    %eax
  94:   3d 00 2f 68 59          cmp    $0x59682f00,%eax
  99:   75 f5                   jne    90 <__Z10iregpreincv+0x10>
  9b:   c9                      leave
  9c:   c3                      ret
  9d:   8d 76 00                lea    0x0(%esi),%esi

000000a0 <__Z7iregaddv>:
  a0:   55                      push   %ebp
  a1:   89 e5                   mov    %esp,%ebp
  a3:   83 ec 10                sub    $0x10,%esp
  a6:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%ebp)
  ad:   31 c0                   xor    %eax,%eax
  af:   90                      nop
  b0:   89 45 fc                mov    %eax,-0x4(%ebp)
  b3:   40                      inc    %eax
  b4:   3d 00 2f 68 59          cmp    $0x59682f00,%eax
  b9:   75 f5                   jne    b0 <__Z7iregaddv+0x10>
  bb:   c9                      leave
  bc:   c3                      ret
  bd:   8d 76 00                lea    0x0(%esi),%esi

000000c0 <_main>:
  c0:   55                      push   %ebp
  c1:   89 e5                   mov    %esp,%ebp
  c3:   83 e4 f0                and    $0xfffffff0,%esp
  c6:   e8 00 00 00 00          call   cb <_main+0xb>
  cb:   e8 30 ff ff ff          call   0 <__Z8ipostincv>
  d0:   e8 4b ff ff ff          call   20 <__Z7ipreincv>
  d5:   e8 66 ff ff ff          call   40 <__Z4iaddv>
  da:   e8 81 ff ff ff          call   60 <__Z11iregpostincv>
  df:   e8 9c ff ff ff          call   80 <__Z10iregpreincv>
  e4:   e8 b7 ff ff ff          call   a0 <__Z7iregaddv>
  e9:   31 c0                   xor    %eax,%eax
  eb:   c9                      leave
  ec:   c3                      ret
  ed:   90                      nop
  ee:   90                      nop
  ef:   90                      nop
Записан
crackedmind
Гость
« Ответ #34 : Январь 30, 2010, 18:37 »

нафига ж вы на int'ах проверяете? разница будет если у объекта будет тяжелый конструктор, типа итератора или еще чего.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #35 : Январь 30, 2010, 20:37 »

нафига ж вы на int'ах проверяете? разница будет если у объекта будет тяжелый конструктор, типа итератора или еще чего.
Классический пример оптимизации не того, что надо бы оптимизировать.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #36 : Январь 31, 2010, 02:25 »

а где я говорил что Qt генерирует исключения?

а где я сказал, что это сказал ты? о_О

Ты дал линк на топик в которой идет дискусия по поводу генерации искючений в программах на Qt. Далее привел линк на конкретный пост в котором приведен листинг обработки исключении.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #37 : Январь 31, 2010, 04:35 »

Похоже на то. Значит компилятору фиолетово какую конструкцию ты используешь, один хрен соптимизирует.
Для простых конструкций - да. В ++библии приводится 2 варианта, примерно таких
Цитировать
// первый
for (i = 0; i < num; ++i)
 dst[ i ] = src[ i ];

// второй
while (src < end)
 *dst++ = *src++;
И говорится что нормальный компилятор сделает примерно одинаковый код.

Изучение кода - дело гораздо более полезное чем это кажется на первый взгляд. Попробуйте заглянуть в код напр "QString = ". Это не так уж трудно, совсем необязательно разбирать все "до команды". И, может быть, Вы увидите по-новому те вещи которые давным-давно знали  Улыбающийся
Записан
SABROG
Гость
« Ответ #38 : Январь 31, 2010, 11:51 »

Изучение кода - дело гораздо более полезное чем это кажется на первый взгляд. Попробуйте заглянуть в код напр "QString = ". Это не так уж трудно, совсем необязательно разбирать все "до команды". И, может быть, Вы увидите по-новому те вещи которые давным-давно знали  Улыбающийся

А что тут необычного?
Код
C++ (Qt)
QString &QString::operator=(const QString &other)
{
   other.d->ref.ref();
   if (!d->ref.deref())
       QString::free(d);
   d = other.d;
   return *this;
}
 
« Последнее редактирование: Январь 31, 2010, 11:54 от SABROG » Записан
niXman
Гость
« Ответ #39 : Январь 31, 2010, 12:37 »

для POD типов, компилятор естественно оптимизирует инкремент/декремент. но с итераторами он ничего не сделает.
Записан
SABROG
Гость
« Ответ #40 : Январь 31, 2010, 15:36 »

для POD типов, компилятор естественно оптимизирует инкремент/декремент. но с итераторами он ничего не сделает.

Из плюсов итераторов. Итераторы призваны скрыть внутреннюю реализацию контейнера, возможность вставки нового элемента без необходимость учитывать индекс, быстрый перебор в контейнерах с произвольным доступом (vector, deque) в отличае от индексного варианта.

Из минусов итераторов. Лучше использовать константные интераторы (если есть такая возможность), т.к. не константные методы типа begin() могут привести к копированию данных в контейнерах с совместным доступом (implicit shared) - QList, QLinkedList. (Qt). Необходимость использовать префиксные операторы, чтобы избежать оверхеда конструктора временного итератора (временной переменной). Необходимость сохранять результат метода .end(), чтобы избежать оверхеда с созданием временного итератора в блоке сравнения (itr != container.end()).

Из всего этого я могу лишь сделать такой вывод, если используется QList или Си массив и нужно только читать из него и проход по нему никак не сказывается на время отклика программы - использовать обычный индексный доступ. И даже не парится насчет постфиксного оператора или префиксного для i.

Если программа работает с вектором в котором куча данных на несколько мегабайт оперативы и нужно его менять туда сюда - использовать итераторы и парится насчет оптимизации. Возможно даже можно запариться насчет отказа от QVector'a в пользу std::vector и своего аллокатора памяти. Можно даже запариться насчет распараллеливания прохода по массиву на всех ядрах процессора QtConcurrent::map(), а то ведь гуишный поток один и использует только 50% мощности компьютера (если ядра 2).
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #41 : Январь 31, 2010, 15:59 »

Из плюсов итераторов. ..

Из минусов итераторов...
Я согласен со всем что Вы написали, но, на мой взгляд это не главное для производительности. Если надо что-то просто просмотреть/перебрать, то проходит все что угодно и не видно особой разницы между std::vector, QVector, QList и просто "С" массивом (который все же самый быстрый  Улыбающийся). Проблемы начинаются когда большие объемы данные "прибывают" и с ними надо что-то делать (часто при этом удалять старые). Вот тут уже разница между QVector и QList может быть в несколько раз. Другой случай - всякие хитрые просмотры/анализы с целью избежать прямого перебора. У меня есть такая задача связанная с делением BSP. Есть желание - обсудим в "алгоритмах".
Записан
Страниц: 1 2 [3]   Вверх
  Печать  
 
Перейти в:  


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