На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ANDLL, ALXR
  
> == 0 ИЛИ ! , C++
   
== 0 ИЛИ !
Гости не могут просматривать результаты голосования.
Гости не могут голосовать 
    В продолжение темы сложного выбора. Обращаю внимание, что речь снова о C++. Примеры, надеюсь, не потребуются
      Потребуются, ибо выбора между сравнением с нулём и логическим "не" никогда не было. В плюсах, в смысле.
        Зависит от ситуации. Что понятнее, то и использую. Это не Python, издержек на сравнение с 0 нет
          Цитата negram @
          Потребуются, ибо выбора между сравнением с нулём и логическим "не" никогда не было. В плюсах, в смысле.

          Это не выбор между нулём и НЕ, это выбор между двумя семантиками проверки нулевого значения
            Когда работаешь с числами - удобнее наверное на 0 проверять. Например делитель числа.
              Цитата KILLER @
              удобнее наверное на 0 проверять

              Так наверное или удобнее? :) Сам-то что используешь и в каких ситуациях?
                Цитата B.V. @
                Так наверное или удобнее? :) Сам-то что используешь и в каких ситуациях?

                Я голоснул за восклицательный знак. Но вообще делитель я бы проверял с помощью if a == 0 togda error, с указателями и прочим юзал бы if !pointer togda error
                  Цитата KILLER @
                  Но вообще делитель я бы проверял с помощью if a == 0 togda error

                  Что-то вспомнилась картинка
                  user posted image
                    Цитата B.V. @
                    Что-то вспомнилась картинка

                    Последний вариант прокатит разве что в скриптовых языках или в каком нибудь C# с Java, а в С++ выхватишь Access Violation.
                      Цитата KILLER @
                      а в С++ выхватишь Access Violation

                      Да нет, выхватишь UB.
                        Цитата B.V. @
                        Да нет, выхватишь UB.

                        Незнаю что там на счет UB. Может в новом стандарте UB будет, помню у Страуструпа вроде было написано что деление на 0 приведет к аппаратной ошибке процессора, и соответственно обрабатывать такую ошибку нужно с помощью какого нибудь SEH исключения. Стандартные исключения ловят только программные ошибки, и надеяться на то что catch отловит деление на 0 глупая затея.

                        Добавлено
                        Хотя помню компилятор майкрософт в дебаге ловит деление на ноль. В релизе хз.
                          Только "!" использую. Ибо вещали (сильно давно), что операция CMP (асм-реализация "==0") крайне тормознутая, а "test" (в случае ! используется, бывает) существенно быстрее!
                            Цитата Славян @
                            Только "!" использую. Ибо вещали (сильно давно), что операция CMP (асм-реализация "==0") крайне тормознутая, а "test" (в случае ! используется, бывает) существенно быстрее!

                            Не представляю даже, как бы ты на явошарпах с питонами писал бы. Повесился наверное раньше :D
                              Цитата B.V. @
                              Цитата negram @
                              Потребуются, ибо выбора между сравнением с нулём и логическим "не" никогда не было. В плюсах, в смысле.

                              Это не выбор между нулём и НЕ, это выбор между двумя семантиками проверки нулевого значения

                              Не было никогда такого выбора в плюсах. Выбор мог быть только у тех, кто воспринимает плюсы как "си с классами". благо, такие уже лет 10-15 как вымерли. :-?
                                Цитата Славян @
                                Ибо вещали (сильно давно), что операция CMP (асм-реализация "==0") крайне тормознутая, а "test" (в случае ! используется, бывает) существенно быстрее!
                                Для сравнения с нулём CMP никогда не использовался. Даже в простейших компиляторах Small-C и Rat-C сравнение с нулём обрабатывалось отдельно от общего случая.
                                Так что тебе лапшу на уши вешали.
                                  Увы, но у меня и сейчас MSVS 2017 так жедает (CMP) без настроек ускорения/оптимизации. :yes-sad:
                                    Ну, видимо так M$ понимает понятие оптимизации. Раз нет оптимизации, значит нельзя даже мелочи оптимизировать.
                                      (x == 0).toString().length() == 4 :crazy:

                                      Добавлено
                                      А вообще фигня холивар. Даёшь табы vs пробелы :yes:

                                      Добавлено
                                      Цитата Славян @
                                      Увы, но у меня и сейчас MSVS 2017 так жедает (CMP) без настроек ускорения/оптимизации.

                                      У тебя странная студия. У меня она даже в дебаге test-ом сравнивает. В релизе с оптимизациями тем более.
                                        Цитата OpenGL @
                                        Даёшь табы vs пробелы

                                        Так уже давно холивар закрыт.

                                        http://intellindent.info/seriously/

                                        Проблема только в том, что инструментарий (IDE, редакторы) не умеют в грамотный индент табами с выравниванием пробелами, поэтому приходится деградировать до all-spaces.
                                          Так нечестно. Я это должен был выложить это в качестве аргумента того, что сторонники пробелов не умеют пользоваться табами :(
                                          Цитата Da$aD @
                                          Проблема только в том, что инструментарий (IDE, редакторы) не умеют в грамотный индент табами с выравниванием пробелами, поэтому приходится деградировать до all-spaces.

                                          Я для этого пользуюсь astyl-ом, автоматически запускаемым при сохранении файла. Он в абсолютном большинстве случаев отличает, когда надо использовать alignment, а когда - indentation - в целом меня вполне устраивает. Пример из статьи отформатировал он правильно.
                                            Цитата OpenGL @
                                            Даёшь табы vs пробелы

                                            Слабо. Даже
                                            ExpandedWrap disabled
                                              () {
                                              }

                                            vs
                                            ExpandedWrap disabled
                                              ()
                                              {
                                              }

                                            как-то, ИМХО, интереснее :)

                                            Добавлено
                                            Между тем, мнения в голосовалке разделились почти поровну. Не ожидал..
                                              Цитата B.V. @
                                              мнения в голосовалке разделились почти поровну
                                              Всё просто: каждой ситуации своё предпочтение. Если переменная хранит признак, то ! в самый раз, а если число, то == 0. Просто это не каждый сформулировать догадывается.
                                                Цитата Qraizer @
                                                Если переменная хранит признак, то ! в самый раз, а если число, то == 0.

                                                Если переменная объявлена но не определена?
                                                Или в условии задачи она точно определена?

                                                Добавлено
                                                Цитата B.V. @
                                                это выбор между двумя семантиками проверки нулевого значения

                                                Все таки проверка числа.
                                                Сообщение отредактировано: Bas -
                                                  Цитата Славян @
                                                  Ибо вещали (сильно давно), что операция CMP (асм-реализация "==0") крайне тормознутая, а "test" (в случае ! используется, бывает) существенно быстрее!

                                                  Все эти "крайне" и "существенно" сильно преувеличены. Регистровые операции cmp r,i и test r,r исполняются одинаково быстро. Разница между ними в размере команды, что косвенно\теоретически может сказаться на задержке их декодирования, да и то только при при определенных "неблагоприятных обстоятельствах". Причем в х86 есть укороченный вариант команды сравнения cmp r/m,i8 с однобайтовой константой, автоматически расширяемой знаком до размера операнда. Соотв-но нормальный (не тупой) компилятор для сравнения с нулем должен использовать именно этот вариант (а не общий, когда размер константы совпадает с размером операнда). Зато cmp на современных x86 имеет преимущество перед test r,r при сравнении операнда в памяти (когда окружающий код не требует его загрузки в регистр), т.к. одна команда cmp m,i8 и декодируется, и все in-order стадии конвеера проходит быстрее, чем пара команд mov r,m + test r,r (хотя на практике разницы может и не быть, т.к. все зависит от окружающего кода, "ветра", "фаз луны" и т.д.).
                                                    Цитата B.V. @
                                                    Это не выбор между нулём и НЕ, это выбор между двумя семантиками проверки нулевого значения

                                                    А почему не между двумя семантиками проверки булевого значения?
                                                      Цитата korvin @
                                                      А почему не между двумя семантиками проверки булевого значения?

                                                      Потому что думаю, что выбор был бы слишком предсказуем: подавляющее большинство выбрало бы вариант !. А вот с численными значениями интереснее
                                                        Цитата korvin @
                                                        А почему не между двумя семантиками проверки булевого значения?
                                                        Булевы значения вообще не принято сравнивать. Ещё в C, где вместо них использовались целые, сравнение признака с нулём считалось плохим стилем, если не ошибкой. А сравнение с TRUE (макрос, равный единице) было именно ошибкой.
                                                          Цитата B.V. @
                                                          Слабо. Даже

                                                          () {
                                                          }

                                                          vs

                                                          ()
                                                          {
                                                          }

                                                          как-то, ИМХО, интереснее

                                                          Я выбираю первый вариант :)
                                                            Для сравнения числовых значений - использую "==", для булевских просто проверка или проверка с отрицанием.
                                                            Для форматирования C/C++ кода все ж использую JavaStyle. Для меня он кажется более компактным и лучше читаемым.
                                                              Цитата Polinom2686 @
                                                              Я выбираю первый вариант
                                                              А я - только второй; по-моему даже в 100% случаев. :yes:
                                                                Цитата Polinom2686 @
                                                                Я выбираю первый

                                                                Цитата Славян @
                                                                А я - только второй

                                                                Воу-воу, погодите до отдельной голосовалки :D
                                                                  Здесь пока - фифти-фифти; в той отдельной думаю, что Полином2pentPro будет с перевесом (по количеству виденых мною исходников...). :yes-sad:
                                                                    Вот и правильно, Славян. А то для }, вишьли, отдельная строка, потому что заканчивает блок, а { почему-то скромненько спаривается с заголовком, что к последующему блоку не имеет никакого отношения, кроме обоснования его наличия.
                                                                    Сообщение отредактировано: Qraizer -
                                                                      Да, а я как бы согласен с вами, Qraizer, но всё равно мне чертовски жаль, что на фигурки уходит две строчки. Ничего тут не могу поделать! Горе, непреодолимое, и всё тут. :'( :'( :'(
                                                                        Цитата Славян @
                                                                        Да, а я как бы согласен с вами, Qraizer, но всё равно мне чертовски жаль, что на фигурки уходит две строчки. Ничего тут не могу поделать! Горе, непреодолимое, и всё тут.

                                                                        Не слушай Qraizer'а - переходи на светлую сторону Силы! :lol: Одну строчку можно сэкономить - используй Java Style.
                                                                          Сокрытие строки не есть светлая сторона, а токмо тёмная! :angry:
                                                                            Цитата Polinom2686 @
                                                                            Я выбираю первый вариант


                                                                            ExpandedWrap disabled
                                                                              func :: ArgType -> ReturnType
                                                                              func arg = statement


                                                                            Problems? :crazy:
                                                                              Цитата Славян @
                                                                              Сокрытие строки

                                                                              не сокрытие - а экономия! не халявщик - а партнер! :lol:
                                                                                Единственным выходом из непреодолимой ситуации вижу только такой: если весь блок вычислений находится правее if'а (for'а, while'а, ...), то компилер бы его сам заключал в фигурные скобки! И экономия и красота, но... мечты?..
                                                                                  Цитата JoeUser @
                                                                                  И экономия и красота, но... мечты?..

                                                                                  Переходи на питон :)
                                                                                    терпеть не могу ! в начале
                                                                                    ExpandedWrap disabled
                                                                                      if (a ...)
                                                                                      if (b ...)
                                                                                      if (!c ...)

                                                                                    неровненько... <_<
                                                                                    Сообщение отредактировано: wind -
                                                                                      А я вот так пишу:
                                                                                      ExpandedWrap disabled
                                                                                        if ( a ...)
                                                                                        if ( b ...)
                                                                                        if (!c ...)
                                                                                      А ещё
                                                                                      ExpandedWrap disabled
                                                                                        a = ...
                                                                                        b =(...)
                                                                                        c+= ...
                                                                                      итп.
                                                                                        Так и не должно быть ровненько! Строки вида "if( a...)" несут суть опосля переменной (вида "if( a!=...)"), а строки же с отрицанием сразу утверждают нечто "if( !c )". Разная идеология! В первых вариантах "a" сравнится с чем-то/с какой-то субстанцией, а в отрицании ужо сказано, что всё тут двоичное грядёт. Так что - норм!! :yes: :yes:
                                                                                          Цитата Славян @
                                                                                          Только "!" использую. Ибо вещали (сильно давно), что операция CMP (асм-реализация "==0") крайне тормознутая, а "test" (в случае ! используется, бывает) существенно быстрее!

                                                                                          ЛОЛШТО?
                                                                                          ExpandedWrap disabled
                                                                                            bool foo1(int a) {
                                                                                                return a == 0;
                                                                                            }
                                                                                             
                                                                                            bool foo2(int a) {
                                                                                                return !a;
                                                                                            }

                                                                                          компилируется в
                                                                                          ExpandedWrap disabled
                                                                                            foo1(int):
                                                                                                    test    edi, edi
                                                                                                    sete    al
                                                                                                    ret
                                                                                            foo2(int):
                                                                                                    test    edi, edi
                                                                                                    sete    al
                                                                                                    ret

                                                                                          Пруф - https://godbolt.org/g/oKkN1v
                                                                                            Да, я тоже только что проверил на типичном примере, и вижу, что оба случая (при настройках оптимизации в максимум) реализуются через test. Но это лишь говорит о том, что оптимизатор понял, что test (делает AND по сути ;) ) быстрее довольно туповатого и прямого CMP! Так что всё норм! :yes: :yes: :yes:

                                                                                            Добавлено
                                                                                            Более того, посмотрел на Release и Debug варианты и что видим:
                                                                                            Release: test reg32, reg32
                                                                                            Debug: cmp dword ptr [], 0
                                                                                            Итог: ! быстрее ==0 при их прямом переводе на маш. код! ч.т.д. :tong:
                                                                                              applegame, а стоило ли рассчитывать, что эти варианты будут различаться? :)

                                                                                              Вот так надо:
                                                                                              ExpandedWrap disabled
                                                                                                for(;x;) return false; return true;
                                                                                              :D

                                                                                              Добавлено
                                                                                              Цитата Славян @
                                                                                              Но это лишь говорит о том, что оптимизатор понял, что test (делает AND по сути ) быстрее довольно туповатого и прямого CMP!
                                                                                              Это лишь говорит о том, что test короче, чем cmp. Скорость работы та же :)
                                                                                              Потому что будет cmp edi,0 (3 байта), а не cmp edi,edi (2 байта, как и test edi,edi).

                                                                                              Добавлено
                                                                                              При этом test edi,edi можно с тем же успехом заменить на and edi,edi или на or edi,edi.
                                                                                              Размер тот же, скорость та же.

                                                                                              Добавлено
                                                                                              У меня сейчас комп не пашет (загрузился с флешки). Кто может скомпилить и прислать дизасм такого кода (для 32-х бит)?
                                                                                              ExpandedWrap disabled
                                                                                                return (!x || x==0x80000000);
                                                                                              Любопытно, как это оптимизируется.
                                                                                              Я поаплодирую, если там будет написано так:
                                                                                              ExpandedWrap disabled
                                                                                                add edi,edi
                                                                                                sete al
                                                                                              (ну там вместо edi может быть что-то другое, разумеется)

                                                                                              Добавлено
                                                                                              Можно ещё так попробовать:
                                                                                              ExpandedWrap disabled
                                                                                                return !(x&0x7FFFFFFF);
                                                                                                ExpandedWrap disabled
                                                                                                  int foo(int x)
                                                                                                  {
                                                                                                    return (!x || x==0x80000000);
                                                                                                  }
                                                                                                   
                                                                                                  int bar(int x)
                                                                                                  {
                                                                                                    return !(x&0x7FFFFFFF);
                                                                                                  }
                                                                                                По скорости. VC2015:
                                                                                                ExpandedWrap disabled
                                                                                                  _TEXT   SEGMENT
                                                                                                  _x$ = 8                                                 ; size = 4
                                                                                                  _bar    PROC                                            ; COMDAT
                                                                                                  ; File c:\disk_f\work\100olymp\q.c
                                                                                                  ; Line 8
                                                                                                          mov     eax, DWORD PTR _x$[esp-4]
                                                                                                          and     eax, 2147483647                         ; 7fffffffH
                                                                                                          neg     eax
                                                                                                          sbb     eax, eax
                                                                                                          inc     eax
                                                                                                  ; Line 9
                                                                                                          ret     0
                                                                                                  _bar    ENDP
                                                                                                  _TEXT   ENDS
                                                                                                  ; Function compile flags: /Ogtpy
                                                                                                  ;       COMDAT _foo
                                                                                                  _TEXT   SEGMENT
                                                                                                  _x$ = 8                                                 ; size = 4
                                                                                                  _foo    PROC                                            ; COMDAT
                                                                                                  ; File c:\disk_f\work\100olymp\q.c
                                                                                                  ; Line 3
                                                                                                          mov     eax, DWORD PTR _x$[esp-4]
                                                                                                          test    eax, eax
                                                                                                          je      SHORT $LN3@foo
                                                                                                          cmp     eax, -2147483648                        ; 80000000H
                                                                                                          je      SHORT $LN3@foo
                                                                                                          xor     eax, eax
                                                                                                  ; Line 4
                                                                                                          ret     0
                                                                                                  $LN3@foo:
                                                                                                  ; Line 3
                                                                                                          mov     eax, 1
                                                                                                  ; Line 4
                                                                                                          ret     0
                                                                                                  _foo    ENDP
                                                                                                  _TEXT   ENDS
                                                                                                ICL2016:
                                                                                                ExpandedWrap disabled
                                                                                                  _TEXT   SEGMENT  PARA PUBLIC FLAT  'CODE'
                                                                                                         ALIGN     16
                                                                                                          PUBLIC _foo
                                                                                                  ; --- foo(int)
                                                                                                  _foo    PROC NEAR
                                                                                                  ; parameter 1: 4 + esp
                                                                                                  .B1.1:                          ; Preds .B1.0
                                                                                                  L1::
                                                                                                                                                             ;2.1
                                                                                                          mov       eax, DWORD PTR [4+esp]                        ;1.5
                                                                                                          test      eax, eax                                      ;3.12
                                                                                                          je        .B1.3         ; Prob 50%                      ;3.12
                                                                                                                                  ; LOE eax ebx ebp esi edi
                                                                                                  .B1.2:                          ; Preds .B1.1
                                                                                                          cmp       eax, -2147483648                              ;3.20
                                                                                                          jne       .B1.4         ; Prob 50%                      ;3.20
                                                                                                                                  ; LOE ebx ebp esi edi
                                                                                                  .B1.3:                          ; Preds .B1.2 .B1.1
                                                                                                          mov       eax, 1                                        ;3.12
                                                                                                          ret                                                     ;3.12
                                                                                                                                  ; LOE eax ebx ebp esi edi
                                                                                                  .B1.4:                          ; Preds .B1.2
                                                                                                          xor       eax, eax                                      ;3.12
                                                                                                                                  ; LOE eax ebx ebp esi edi
                                                                                                  .B1.5:                          ; Preds .B1.4
                                                                                                          ret                                                     ;3.12
                                                                                                          ALIGN     16
                                                                                                                                  ; LOE
                                                                                                  ; mark_end;
                                                                                                  _foo ENDP
                                                                                                         ALIGN     16
                                                                                                          PUBLIC _bar
                                                                                                  ; --- bar(int)
                                                                                                  _bar    PROC NEAR
                                                                                                  ; parameter 1: 4 + esp
                                                                                                  .B2.1:                          ; Preds .B2.0
                                                                                                  L2::
                                                                                                                                                             ;7.1
                                                                                                          xor       eax, eax                                      ;8.14
                                                                                                          mov       edx, 1                                        ;8.14
                                                                                                          test      DWORD PTR [4+esp], 2147483647                 ;8.14
                                                                                                          cmove     eax, edx                                      ;8.14
                                                                                                          ret                                                     ;8.14
                                                                                                          ALIGN     16
                                                                                                                                  ; LOE
                                                                                                  ; mark_end;
                                                                                                  _bar ENDP
                                                                                                  ;_bar   ENDS
                                                                                                  _TEXT   ENDS
                                                                                                По размеру. VC2015:
                                                                                                ExpandedWrap disabled
                                                                                                  PUBLIC  _foo
                                                                                                  PUBLIC  _bar
                                                                                                  ; Function compile flags: /Ogspy
                                                                                                  ;       COMDAT _bar
                                                                                                  _TEXT   SEGMENT
                                                                                                  _x$ = 8                                                 ; size = 4
                                                                                                  _bar    PROC                                            ; COMDAT
                                                                                                  ; File c:\disk_f\work\100olymp\q.c
                                                                                                  ; Line 8
                                                                                                          mov     eax, DWORD PTR _x$[esp-4]
                                                                                                          and     eax, 2147483647                         ; 7fffffffH
                                                                                                          neg     eax
                                                                                                          sbb     eax, eax
                                                                                                          inc     eax
                                                                                                  ; Line 9
                                                                                                          ret     0
                                                                                                  _bar    ENDP
                                                                                                  _TEXT   ENDS
                                                                                                  ; Function compile flags: /Ogspy
                                                                                                  ;       COMDAT _foo
                                                                                                  _TEXT   SEGMENT
                                                                                                  _x$ = 8                                                 ; size = 4
                                                                                                  _foo    PROC                                            ; COMDAT
                                                                                                  ; File c:\disk_f\work\100olymp\q.c
                                                                                                  ; Line 3
                                                                                                          cmp     DWORD PTR _x$[esp-4], 0
                                                                                                          je      SHORT $LN3@foo
                                                                                                          cmp     DWORD PTR _x$[esp-4], -2147483648       ; 80000000H
                                                                                                          je      SHORT $LN3@foo
                                                                                                          xor     eax, eax
                                                                                                  ; Line 4
                                                                                                          ret     0
                                                                                                  $LN3@foo:
                                                                                                  ; Line 3
                                                                                                          xor     eax, eax
                                                                                                          inc     eax
                                                                                                  ; Line 4
                                                                                                          ret     0
                                                                                                  _foo    ENDP
                                                                                                  _TEXT   ENDS
                                                                                                ICL2016:
                                                                                                ExpandedWrap disabled
                                                                                                  _TEXT   SEGMENT  DWORD PUBLIC FLAT  'CODE'
                                                                                                          PUBLIC _foo
                                                                                                  ; --- foo(int)
                                                                                                  _foo    PROC NEAR
                                                                                                  ; parameter 1: 4 + esp
                                                                                                  .B1.1:                          ; Preds .B1.0
                                                                                                  L1::
                                                                                                                                                             ;2.1
                                                                                                          mov       eax, DWORD PTR [4+esp]                        ;1.5
                                                                                                          test      eax, eax                                      ;3.12
                                                                                                          je        .B1.3         ; Prob 50%                      ;3.12
                                                                                                                                  ; LOE eax ebx ebp esi edi
                                                                                                  .B1.2:                          ; Preds .B1.1
                                                                                                          cmp       eax, -2147483648                              ;3.20
                                                                                                          jne       .B1.4         ; Prob 50%                      ;3.20
                                                                                                                                  ; LOE ebx ebp esi edi
                                                                                                  .B1.3:                          ; Preds .B1.2 .B1.1
                                                                                                          push      1                                             ;3.12
                                                                                                          pop       eax                                           ;3.12
                                                                                                          ret                                                     ;3.12
                                                                                                                                  ; LOE eax ebx ebp esi edi
                                                                                                  .B1.4:                          ; Preds .B1.2
                                                                                                          xor       eax, eax                                      ;3.12
                                                                                                                                  ; LOE eax ebx ebp esi edi
                                                                                                  .B1.5:                          ; Preds .B1.4
                                                                                                          ret                                                     ;3.12
                                                                                                                                  ; LOE
                                                                                                  ; mark_end;
                                                                                                  _foo ENDP
                                                                                                          PUBLIC _bar
                                                                                                  ; --- bar(int)
                                                                                                  _bar    PROC NEAR
                                                                                                  ; parameter 1: 4 + esp
                                                                                                  .B2.1:                          ; Preds .B2.0
                                                                                                  L2::
                                                                                                                                                             ;7.1
                                                                                                          xor       eax, eax                                      ;8.14
                                                                                                          test      DWORD PTR [4+esp], 2147483647                 ;8.14
                                                                                                          sete      al                                            ;8.14
                                                                                                          ret                                                     ;8.14
                                                                                                                                  ; LOE
                                                                                                  ; mark_end;
                                                                                                  _bar ENDP
                                                                                                  ;_bar   ENDS
                                                                                                  _TEXT   ENDS
                                                                                                64 бита приводить?
                                                                                                Сообщение отредактировано: Qraizer -
                                                                                                  Цитата Qraizer @
                                                                                                  64 бита приводить?
                                                                                                  Не надо, спасибо.

                                                                                                  Цитата Qraizer @
                                                                                                          test      DWORD PTR [4+esp], 2147483647                 ;8.14
                                                                                                          sete      al  
                                                                                                  Вот это уже нормально :good:

                                                                                                  Но Intel что-то гонит. Оптимизация по размеру (приведённый чуть выше код) должна быть быстрее, ибо cmovcc медленнее, чем setcc.

                                                                                                  Интересен вариант с icl в случае, если x будет не в стеке, а в регистре...
                                                                                                    Медленнее, на такт. Но она может быть спараллелена посредством задействования обоих значений результата, тогда как setcc не может.

                                                                                                    Добавлено
                                                                                                    Цитата Jin X @
                                                                                                    Интересен вариант с icl в случае, если x будет не в стеке, а в регистре...
                                                                                                    Ок, fastcall. По скорости:
                                                                                                    ExpandedWrap disabled
                                                                                                      _TEXT   SEGMENT  PARA PUBLIC FLAT  'CODE'
                                                                                                             ALIGN     16
                                                                                                              PUBLIC @foo@4
                                                                                                      ; --- foo(int)
                                                                                                      @foo@4  PROC NEAR
                                                                                                      ; parameter 1: ecx
                                                                                                      .B1.1:                          ; Preds .B1.0
                                                                                                      L1::
                                                                                                                                                                 ;2.1
                                                                                                              test      ecx, ecx                                      ;3.12
                                                                                                              je        .B1.3         ; Prob 50%                      ;3.12
                                                                                                                                      ; LOE ecx ebx ebp esi edi
                                                                                                      .B1.2:                          ; Preds .B1.1
                                                                                                              cmp       ecx, -2147483648                              ;3.20
                                                                                                              jne       .B1.4         ; Prob 50%                      ;3.20
                                                                                                                                      ; LOE ebx ebp esi edi
                                                                                                      .B1.3:                          ; Preds .B1.2 .B1.1
                                                                                                              mov       eax, 1                                        ;3.12
                                                                                                              ret                                                     ;3.12
                                                                                                                                      ; LOE eax ebx ebp esi edi
                                                                                                      .B1.4:                          ; Preds .B1.2
                                                                                                              xor       eax, eax                                      ;3.12
                                                                                                                                      ; LOE eax ebx ebp esi edi
                                                                                                      .B1.5:                          ; Preds .B1.4
                                                                                                              ret                                                     ;3.12
                                                                                                              ALIGN     16
                                                                                                                                      ; LOE
                                                                                                      ; mark_end;
                                                                                                      @foo@4 ENDP
                                                                                                             ALIGN     16
                                                                                                              PUBLIC @bar@4
                                                                                                      ; --- bar(int)
                                                                                                      @bar@4  PROC NEAR
                                                                                                      ; parameter 1: ecx
                                                                                                      .B2.1:                          ; Preds .B2.0
                                                                                                      L2::
                                                                                                                                                                 ;7.1
                                                                                                              xor       eax, eax                                      ;8.14
                                                                                                              mov       edx, 1                                        ;8.14
                                                                                                              test      ecx, 2147483647                               ;8.14
                                                                                                              cmove     eax, edx                                      ;8.14
                                                                                                              ret                                                     ;8.14
                                                                                                              ALIGN     16
                                                                                                                                      ; LOE
                                                                                                      ; mark_end;
                                                                                                      @bar@4 ENDP
                                                                                                      ;@bar@4 ENDS
                                                                                                      _TEXT   ENDS
                                                                                                    По размеру:
                                                                                                    ExpandedWrap disabled
                                                                                                      _TEXT   SEGMENT  DWORD PUBLIC FLAT  'CODE'
                                                                                                              PUBLIC @foo@4
                                                                                                      ; --- foo(int)
                                                                                                      @foo@4  PROC NEAR
                                                                                                      ; parameter 1: ecx
                                                                                                      .B1.1:                          ; Preds .B1.0
                                                                                                      L1::
                                                                                                                                                                 ;2.1
                                                                                                              test      ecx, ecx                                      ;3.12
                                                                                                              je        .B1.3         ; Prob 50%                      ;3.12
                                                                                                                                      ; LOE ecx ebx ebp esi edi
                                                                                                      .B1.2:                          ; Preds .B1.1
                                                                                                              cmp       ecx, -2147483648                              ;3.20
                                                                                                              jne       .B1.4         ; Prob 50%                      ;3.20
                                                                                                                                      ; LOE ebx ebp esi edi
                                                                                                      .B1.3:                          ; Preds .B1.2 .B1.1
                                                                                                              push      1                                             ;3.12
                                                                                                              pop       eax                                           ;3.12
                                                                                                              ret                                                     ;3.12
                                                                                                                                      ; LOE eax ebx ebp esi edi
                                                                                                      .B1.4:                          ; Preds .B1.2
                                                                                                              xor       eax, eax                                      ;3.12
                                                                                                                                      ; LOE eax ebx ebp esi edi
                                                                                                      .B1.5:                          ; Preds .B1.4
                                                                                                              ret                                                     ;3.12
                                                                                                                                      ; LOE
                                                                                                      ; mark_end;
                                                                                                      @foo@4 ENDP
                                                                                                              PUBLIC @bar@4
                                                                                                      ; --- bar(int)
                                                                                                      @bar@4  PROC NEAR
                                                                                                      ; parameter 1: ecx
                                                                                                      .B2.1:                          ; Preds .B2.0
                                                                                                      L2::
                                                                                                                                                                 ;7.1
                                                                                                              test      ecx, 2147483647                               ;8.14
                                                                                                              push      0                                             ;8.14
                                                                                                              pop       eax                                           ;8.14
                                                                                                              sete      al                                            ;8.14
                                                                                                              ret                                                     ;8.14
                                                                                                                                      ; LOE
                                                                                                      ; mark_end;
                                                                                                      @bar@4 ENDP
                                                                                                      ;@bar@4 ENDS
                                                                                                      _TEXT   ENDS
                                                                                                      Qraizer, с чем она может быть спараллелена, когда её работа зависит от результата предыдущей операции (всех 3-х предыдущих инструкций, я даже скажу)?

                                                                                                      gcc, кстати, срабатывает как xor+test+sete (xor+and+sete для регистра) при оптимизации по скорости для обоих вариантов кода.
                                                                                                      А вот просто !x или x==0 он компилит аж в:
                                                                                                      ExpandedWrap disabled
                                                                                                        mov edx,[esp+4]
                                                                                                        xor eax,eax
                                                                                                        test edx,edx
                                                                                                        sete al


                                                                                                      Добавлено
                                                                                                      Цитата Qraizer @
                                                                                                              push      1
                                                                                                              pop       eax  
                                                                                                      Жесть какая!
                                                                                                      Тогда бы уж сделали
                                                                                                      ExpandedWrap disabled
                                                                                                        xor eax,eax
                                                                                                        inc eax
                                                                                                      Размер тот же, но хоть быстрее должно быть...

                                                                                                      Добавлено
                                                                                                      Цитата Jin X @
                                                                                                      xor+test+sete
                                                                                                      Зачем тут xor eax,eax, когда я объявляю тип функции bool? Он же байтовый!
                                                                                                      Сообщение отредактировано: Jin X -
                                                                                                        Цитата Jin X @
                                                                                                        с чем она может быть спараллелена, когда её работа зависит от результата предыдущей операции
                                                                                                        С последующими действиями. Может использоваться либо eax, либо edx, но какой именно, станет известно лишь позднее. Временно можно использовать два потока исполнения, один из которых будет впоследствии отброшен, а второй, использующий "правильный" risc-регистр, переотображён на eax. То же можно сделать с setcc, также задействуя два risc-регистра, однако тут больше сложностей с подготовкой значения для второго. В отличие от cmovcc, где оба значения уже подготовлены и лежат в регистрах, для setcc значения 0 и 1, причём чётко байтовые, нужно подготавливать явно. Вероятно, по этой причине микрокод для них может отличаться.

                                                                                                        Добавлено
                                                                                                        Цитата Jin X @
                                                                                                        Жесть какая!
                                                                                                        Соседние push/pop не имеют штрафов по зависимостям. Они спецом для этого оптимизированы. Пара xor/inс зависит от ALU

                                                                                                        Добавлено
                                                                                                        Цитата Jin X @
                                                                                                        Зачем тут xor eax,eax, когда я объявляю тип функции bool? Он же байтовый!
                                                                                                        Ну я же привёл прототипы. Там int. Если хочешь C++, где есть честный bool, то это будут другие прототипы.

                                                                                                        Добавлено
                                                                                                        Проверил на intel, никакой разницы. Он всегда предпочитает работать с полноразмерными регистрами, ибо так куда эффективнее работает микрокод. (Вообще, даже самые древние мануалы советуют никогда не смешивать разноразмерные данные в зависимых инструкциях.) А вот visual немного удивил:
                                                                                                        ExpandedWrap disabled
                                                                                                          _TEXT   SEGMENT
                                                                                                          ?bar@@YI_NH@Z PROC                                      ; bar, COMDAT
                                                                                                          ; _x$ = ecx
                                                                                                          ; File c:\users\shmatko\documents\intel\документация\qq.cpp
                                                                                                          ; Line 8
                                                                                                                  test    ecx, 2147483647                         ; 7fffffffH
                                                                                                                  sete    al
                                                                                                          ; Line 9
                                                                                                                  ret     0
                                                                                                          ?bar@@YI_NH@Z ENDP                                      ; bar
                                                                                                          _TEXT   ENDS
                                                                                                          ; Function compile flags: /Ogtpy
                                                                                                          ;       COMDAT ?foo@@YI_NH@Z
                                                                                                          _TEXT   SEGMENT
                                                                                                          ?foo@@YI_NH@Z PROC                                      ; foo, COMDAT
                                                                                                          ; _x$ = ecx
                                                                                                          ; File c:\users\shmatko\documents\intel\документация\qq.cpp
                                                                                                          ; Line 3
                                                                                                                  test    ecx, ecx
                                                                                                                  je      SHORT $LN3@foo
                                                                                                                  cmp     ecx, -2147483648                        ; 80000000H
                                                                                                                  je      SHORT $LN3@foo
                                                                                                                  xor     al, al
                                                                                                          ; Line 4
                                                                                                                  ret     0
                                                                                                          $LN3@foo:
                                                                                                          ; Line 3
                                                                                                                  mov     al, 1
                                                                                                          ; Line 4
                                                                                                                  ret     0
                                                                                                          ?foo@@YI_NH@Z ENDP                                      ; foo
                                                                                                          _TEXT   ENDS
                                                                                                        Это по скорости.

                                                                                                        Добавлено
                                                                                                        Тока эта... сегодня VC2017.

                                                                                                        Добавлено
                                                                                                        P.S.
                                                                                                        Цитата Qraizer @
                                                                                                        Временно можно использовать два потока исполнения...
                                                                                                        Забыл добавить, что это лишь мои рассуждения, почему такое может иметь место. Как оно на самом деле, без понятия.
                                                                                                        Сообщение отредактировано: Qraizer -
                                                                                                          Цитата Qraizer @
                                                                                                          Соседние push/pop не имеют штрафов по зависимостям.
                                                                                                          Так, дело не в зависимости, а в использовании стека (то бишь памяти, а это время).

                                                                                                          Цитата Qraizer @
                                                                                                          Ну я же привёл прототипы. Там int. Если хочешь C++, где есть честный bool, то это будут другие прототипы.
                                                                                                          Я заменил int на bool и откомпилил gcc, но результат всё равно почему-то пишется в eax.

                                                                                                          Цитата Qraizer @
                                                                                                          Вообще, даже самые древние мануалы советуют никогда не смешивать разноразмерные данные в зависимых инструкциях
                                                                                                          Не спорю (кстати, это может быть причиной использования cmov), просто здесь всё равно используется sete, поэтому xor eax,eax ничего ускорить не должен, по идее...
                                                                                                          Возможно, просто компилер устроен так, что оперирует только полными регистрами. Вот, кстати, надо посмотреть как он будет char возвращать - как байт или дворд. Intel и gcc.
                                                                                                            Цитата Jin X @
                                                                                                            Так, дело не в зависимости, а в использовании стека (то бишь памяти, а это время).
                                                                                                            Ничего страшного. Ляжет в L1 кэша, ибо вершина стека да в кэш.промахе... когда такое бывало-то, оттуда же прочтётся, а в память запишется в фоне при отбросе кеш.строк, да и то не факт, что не перезапишется к тому времени мульён раз другими данными.
                                                                                                              Цитата Qraizer @
                                                                                                              Ничего страшного. Ляжет в L1 кэша
                                                                                                              Ляжет, но обращение к кэшу тоже требует времени. Кэш (даже L1) - это же не регистры.
                                                                                                                Так это не отнимет тактов. Ещё в i486 была очередь отложенных записей, которые не тормозили ALU, в отличие от чтений, а, если не ошибаюсь, в P6 появилась фича вытаскивать эти данные прям из очереди, т.е. даже без обращения к L1. Поспрашивай leo, он больше об этом всём знает.
                                                                                                                  По поводу cmov'ов Агнер пишет так:
                                                                                                                  Цитата
                                                                                                                  The advantage of a conditional move is that it avoids branch mispredictions. But it has the disadvantage that it increases the length of a dependency chain, while a predicted branch breaks the dependency chain. If the code in example 9.9c is part of a dependency chain then the cmov instruction adds to the length of the chain. The latency of cmov is two clock cycles on Intel processors, and one clock cycle on AMD processors.
                                                                                                                  9.9c - это
                                                                                                                  ExpandedWrap disabled
                                                                                                                     ; Example 9.9c. Branch implemented with conditional move
                                                                                                                     mov eax, [b]
                                                                                                                     cmp eax, [c]
                                                                                                                     mov eax, [d]
                                                                                                                     cmovng eax, [e]
                                                                                                                  p.s. Про цепочку зависимостей, в общем-то, оно и так понятно.

                                                                                                                  И вот ещё:
                                                                                                                  Цитата
                                                                                                                  If a conditional jump is used for setting a Boolean variable to 0 or 1 then it is often more efficient to use the conditional set instruction.
                                                                                                                  Здесь он, конечно, сравнивает setcc с jcc, но всё же не про movcc не пишет, а именно про setcc.

                                                                                                                  Цитата Qraizer @
                                                                                                                  в P6 появилась фича вытаскивать эти данные прям из очереди, т.е. даже без обращения к L1
                                                                                                                  Может быть, конечно.
                                                                                                                  Но я могу лишь судить по таблице скоростей и задержек: http://agner.org/optimize/instruction_tables.pdf
                                                                                                                  Ну и мои тесты показывают, что push 1+pop eax работает медленнее, чем xor eax,eax+inc eax, хотя я понимаю, что при других сочетаниях результаты могут быть другими.
                                                                                                                  Но в любом случае вряд ли push/pop будет когда-либо быстрее, чем xor/inc.

                                                                                                                  Добавлено
                                                                                                                  Собственно, хочется понять: это продуманный умысел Intel (и тогда в чём он?) или недочёт (что было бы странно для производителя процессоров)?

                                                                                                                  Добавлено
                                                                                                                  Цитата Qraizer @
                                                                                                                  Поспрашивай leo, он больше об этом всём знает.
                                                                                                                  Я его, пожалуй, приглашу в эту тему :)
                                                                                                                    Цитата Jin X @
                                                                                                                    Собственно, хочется понять: это продуманный умысел Intel (и тогда в чём он?) или недочёт (что было бы странно для производителя процессоров)?
                                                                                                                    Думаю, никаких теорий заговоров. У него просто мало информации. Если использовать эти функции в контексте, да ещё и инлайнить, код может отличаться от голых __fastcall функций разительно.
                                                                                                                      Цитата Jin X @
                                                                                                                      Ну и мои тесты показывают, что push 1+pop eax работает медленнее, чем xor eax,eax+inc eax, хотя я понимаю, что при других сочетаниях результаты могут быть другими.
                                                                                                                      Но в любом случае вряд ли push/pop будет когда-либо быстрее, чем xor/inc.
                                                                                                                      На AMD, судя по таймингам, одинаково, только комбинация push+pop немного длиннее. на intel push+pop выполняется дольше.
                                                                                                                      А непосредственная засылка единицы в регистр на обоих процессорах будет работать ещё быстрее.
                                                                                                                        Я вполне допускаю, что засылка значения быстрее и всё такое, но всё же идеологически вижу это медленнее/неправильнее по таким причинам: засылка значения - это как привоз некими 32-мя фурами издалека значения 0 или 1 (распараллелили), а XOR - это работат тут, на месте, недалёкая=простая в геометрико-транзисторном виде, тоже параллельная 32 раза, - должна быть существенно быстрее! Будет ещё, конечно, INC, но и он ничего извне не просит, а может и тут, на месте, молотить. Так что... :yes-sad:

                                                                                                                        Добавлено
                                                                                                                        Цитата Jin X @
                                                                                                                        При этом test edi,edi можно с тем же успехом заменить на and edi,edi или на or edi,edi.
                                                                                                                        Размер тот же, скорость та же.
                                                                                                                        Это они практически такие же, но идеологически test не меняет регистр, а лишь "проверяет" (and "в уме") биты, посему ДОЛЖЕН быть быстрее. :yes-sad:
                                                                                                                          Цитата amk @
                                                                                                                          посему ДОЛЖЕН быть быстрее.

                                                                                                                          Лично я, чтобы так плотно, на асме не прогал лет 20 точно. Но одно - помню, нет такого понятия "ДОЛЖЕН". Есть документация.
                                                                                                                            Я имел ввиду схемотехническую реализацию, аппаратную. И цитата та не от amk. ;)
                                                                                                                              Цитата Славян @
                                                                                                                              засылка значения - это как привоз некими 32-мя фурами издалека значения 0 или 1 (распараллелили)
                                                                                                                              Это не завоз издалека. Это когда ты приходишь куда-то, а нужное значение у тебя тут-же с собой, в кармане, и не надо никого за ним куда-то посылать, ни из подручных средств на месте готовить.
                                                                                                                                Э, погодьте-ка! Регистр всё же кусок памяти процессора, такие-то ячейки на подложке, элементы микросхемы. Поэтому ничего в кармане у них вечно нет, - всё откуда-то завозится. И непосредственное значение, даже бит его, всё равно придёт=принесётся! А вот нанофабрика по созданию операции XOR вполне может быть тут же, в шаге; так что мне мыслится это быстрее. Хоть и соглашусь, что практическая реализация может статься и наоборот сделана. :yes-sad:
                                                                                                                                  Непосредственные данные (в диапазоне от -128 до 127 это всего 1 байт) поступают на исполнение одновременно с командой, так что никаких дополнительных задержек они в принципе создать не могут. А вот для команды XOR приходится задействовать ALU - пересылать данные туда-сюда. Хорошо, что требуется на это всего один такт. Но потом-то приходится ещё и инкремент делать. А это отдельная команда, вдобавок завязанная на результат предыдущей, запараллелить её не получится.
                                                                                                                                    Ну я вижу работу декодера как-то так:
                                                                                                                                    ExpandedWrap disabled
                                                                                                                                      if( XOR )
                                                                                                                                      {
                                                                                                                                        switch( операнды )
                                                                                                                                        {
                                                                                                                                          case reg32s:
                                                                                                                                              if( reg32a vs reg32a ) обнулить!( reg32a );
                                                                                                                                              else ФабрикаXOR(...);
                                                                                                                                              ...
                                                                                                                                          case память:
                                                                                                                                              ВытащитьДанные();
                                                                                                                                              ФабрикаXOR(...);
                                                                                                                                              ...
                                                                                                                                          case ...
                                                                                                                                        }
                                                                                                                                      }
                                                                                                                                    А команды mov reg32, data8 всё равно ж нет, так что приходится зачитывать аж 32 бита, что долго и много.
                                                                                                                                      Цитата amk @
                                                                                                                                      На AMD, судя по таймингам, одинаково, только комбинация push+pop немного длиннее
                                                                                                                                      Почему длиннее? push 1 = 2 байта, pop eax = 1 байт, итого 3.
                                                                                                                                      xor eax,eax = 2 байта, inc eax = 1 байт (на 32-х битах, не 64), итого тоже 3.

                                                                                                                                      Цитата amk @
                                                                                                                                      А непосредственная засылка единицы в регистр на обоих процессорах будет работать ещё быстрее.
                                                                                                                                      Это понятно, но тут оптимизации по размеру.

                                                                                                                                      Цитата Славян @
                                                                                                                                      Это они практически такие же, но идеологически test не меняет регистр, а лишь "проверяет" (and "в уме") биты, посему ДОЛЖЕН быть быстрее.
                                                                                                                                      OMG, в каком "уме"? "В уме" может так же означать (в теории), что его нужно куда-то скопировать и там сделать and. Это как вариант. Как там в микрокоде конкретно реализовано - не знаю. Но это всё демагогия. А надо смотреть на таблицы, которые говорят, что на Nehalem, к примеру, mov, xor, test, or, and, add, sub, inc и dec (для операция reg,reg или reg,imm) имеют одни и те же характеристики: используемые порты, кол-во микроопераций и latency. К тому же, xor с inc не могут параллелиться даже чисто теоретически, т.к. inc зависим от результата предыдущей операции - xor.
                                                                                                                                      Ещё в качестве примера: inc eax по твоей логике должен быть быстрее, чем add eax,1, однако на Pentium 4 он работает медленнее, т.к. не меняет значения флага CF, что требует дополнительной микрооперации.
                                                                                                                                      Ещё "в теории" loop должен работать быстрее, чем dec eax + jnz, но вот на практике всё иначе (ещё со времён царя Гороха)...

                                                                                                                                      Цитата Славян @
                                                                                                                                      Ну я вижу работу декодера как-то так
                                                                                                                                      Видь. А Intel видим её по-своему :tong:
                                                                                                                                        Цитата Jin X @
                                                                                                                                        Ещё в качестве примера: inc eax по твоей логике должен быть быстрее, чем add eax,1, однако на Pentium 4 он работает медленнее, т.к. не меняет значения флага CF, что требует дополнительной микрооперации.
                                                                                                                                        Ну во многих древних книжках по ASM'у так и писалось, что INC - короткая и быстрая, а не то что ADD. Что там поменяли существенно с годами - неясно, но всё же думается, что первые инженеры процессоров не зря сделали такую команду отдельно, - нутром чуяли её специфику, а потому и ускорение. :yes: :yes:
                                                                                                                                          Славян, напомню, что раньше память ОЗУ была в дифиците и измерялась килобайтами, а не гигабайтами, поэтому вполне логично было иметь 1-байтовые инструкции как альтернативу 3-байтовым - это раз.
                                                                                                                                          Ну и да, во времена 8086 процессора add (reg,imm) выполнялась за 4 такта, а inc - за 3. Но с тех пор воды утекло целое озеро Байкал...
                                                                                                                                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                                                                          0 пользователей:


                                                                                                                                          Рейтинг@Mail.ru
                                                                                                                                          [ Script execution time: 0,1568 ]   [ 18 queries used ]   [ Generated: 28.03.24, 10:37 GMT ]