1. Си / Говнокод #25307

    −1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    void sort8(uint64_t a[8])
    {
      uint64_t a0;
      uint64_t a1;
      uint64_t a2;
      uint64_t a3;
      uint64_t a4;
      uint64_t a5;
      uint64_t a6;
      uint64_t a7;
     
      SORT2(a[0], a[1], a0, a1);
      SORT2(a[2], a[3], a2, a3);
      SORT2(a[4], a[5], a4, a5);
      SORT2(a[6], a[7], a6, a7);
    
      uint64_t a_tmp[8];
    
      MERGE_2_4(a0, a1, a2, a3, a_tmp[0], a_tmp[1], a_tmp[2], a_tmp[3]);
      MERGE_2_4(a4, a5, a6, a7, a_tmp[4], a_tmp[5], a_tmp[6], a_tmp[7]);
    
      uint64_t *ptra1 = &a_tmp[0];
      uint64_t *ptra2 = &a_tmp[4];
      
      for (size_t i = 0; i < 4; i++)
      {
        if (*ptra1 < *ptra2)
        {
          a[i] = *ptra1;
          ptra1++;
        }
        else
        {
          a[i] = *ptra2;
          ptra2++;
        }
      }
    
      for (size_t i = 4; i < 8; i++)
      {
        if (ptra1 == &a_tmp[4])
        {
          while (ptra2 != &a_tmp[8])
          {
            a[i++] = *ptra2;
            ptra2++;
          }
          break;
        }
        
        if (ptra2 == &a_tmp[8])
        {
          while (ptra1 != &a_tmp[4])
          {
            a[i++] = *ptra1;
            ptra1++;
          }
          break;
        }
    
    
        if (*ptra1 < *ptra2)
        {
          a[i] = *ptra1;
          ptra1++;
        }
        else
        {
          a[i] = *ptra2;
          ptra2++;
        }
    
      }
    }

    Мерж сорт, специализированный на 8 элементов. Вот доказательство корректности https://paste.debian.net/hidden/cce6d31a/

    Запостил: j123123, 13 Января 2019

    Комментарии (137) RSS

    • Ах да, макросня для смерживания и сортировки кусков по 2 элемента
      #define SORT2(a, b, a1, b1) \
        do {if (a < b) {a1 = a; b1 = b;} else {a1 = b; b1 = a;};} while (0)
      
      /*
      #define SORT2(a, b, a1, b1) \
        do {typeof(a1) temp_var[3] = {a, b, a}; a1 = temp_var[(a > b)]; b1 = temp_var[(a > b)+1];} while (0)
      */
      
      #define MERGE_2_4(a0, a1, a2, a3, as0, as1, as2, as3) \
      do \
      { \
        if (a0 > a2) \
        { \
          if (a0 > a3) \
          { \
            as0 = a2; \
            as1 = a3; \
            as2 = a0; \
            as3 = a1; \
          } \
          else \
          { \
            if (a1 > a3) \
            { \
              as0 = a2; \
              as1 = a0; \
              as2 = a3; \
              as3 = a1; \
            } \
            else \
            { \
              as0 = a2; \
              as1 = a0; \
              as2 = a1; \
              as3 = a3; \
            } \
          } \
        } \
        else \
        { \
          if (a2 >= a1) \
          { \
            as0 = a0; \
            as1 = a1; \
            as2 = a2; \
            as3 = a3; \
          } \
          else \
          { \
            if (a3 >= a1) \
            { \
              as0 = a0; \
              as1 = a2; \
              as2 = a1; \
              as3 = a3; \
            } \
            else \
            { \
              as0 = a0; \
              as1 = a2; \
              as2 = a3; \
              as3 = a1; \
            } \
          } \
        } \
      } while (0)


      Эта херня по итогам уделывает в скорости std::sort, если им сортировать куски по 8 элементов.
      Ответить
      • Мне всегда было интересно, зачем оборачивать в do{ ... }while(0)? почему не { ... }?
        Ответить
        • Вроде я когда-то тут описывал заповеди макроёбства, поищи.
          Ответить
        • https://www.reddit.com/r/C_Programming/comments/2xz15h/why_is_this_code_using_a_dowhile0_in_a_macro/cp4ra4w
          Ответить
        • матапушта у тебя есть макрос с двумя стейтментами, и ты оборачиваешь его в блок что бы его можно было if, например

          а если после него поставить точку с зопятой, то получится

          {pituh(); koko();};
          и будет ошибка
          а
          {pituh(); koko();} while(0); -- не будет
          Ответить
          • Кстати, о хаках. Недавно видел чудесное:
            $ pwd | awk -F/ '{print $NF}'


            NF е колво колонок. $NF, таким образом, есть последняя колонка. Так чуваки узнавали имя текущей папки.
            Ответить
          • Чушь, нет здесь ошибки. Про пустой апиратор что-нибудь слышал?

            А, внутри if'а. Сорре.
            Ответить
      • Макроёбство на службе битоёбства.

        Иногда даже жалко что мне в работе такие задачи решать не приходится. Или нет. Не жалко. В жопу такое дебажить потом.
        Ответить
    • А чего последний мёрж не заанроллен?
      Ответить
      • Компилятор такой цикл должен сам анролльнуть на высокой оптимизации
        Ответить
      • Хотя вообще да, можно было б запилить еще кроме вот того MERGE_2_4 еще MERGE_4_8 и например MERGE_8_16. Только тут уже кодогенерация нужна, я это руками заебусь делать.
        Ответить
        • Намазал тебе лицо говном, тебе понравилось.
          Ответить
          • если тебе нравится это не значит что всем нравится
            Ответить
    • Вот даже бенчмаркалку сделал через /dev/urandom, даже с крестоговном https://paste.debian.net/hidden/4a8b71cf/

      Кто-нибудь сможет быстрее сортировку на восемь uint64_t сделать (можно даже попробовать какое-нибудь SSE, если оно чем-то сможет помочь)? std::sort отстает от этого кода на GCC.
      Ответить
      • > uint64_t
        Подстраховался от эсэсёбства? :)
        Ответить
      • Вот такая хуйня медленнее чем твоя?
        void sort2(uint64_t a, uint64_t b, uint64_t& oa, uint64_t& ob) {
            if (a < b) {
                oa = a;
                ob = b;
            } else {
                oa = b;
                ob = a;
            }
        }
        
        void sort8(uint64_t a[8]) {
            uint64_t b[8], c[8], d[8], e[8], f[8];
            sort2(a[0], a[1], b[0], b[1]); sort2(a[2], a[3], b[2], b[3]); sort2(a[4], a[5], b[4], b[5]); sort2(a[6], a[7], b[6], b[7]);
            sort2(b[0], b[3], c[0], c[3]); sort2(b[1], b[2], c[1], c[2]); sort2(b[4], b[7], c[4], c[7]); sort2(b[5], b[6], c[5], c[6]);
            sort2(c[0], c[1], d[0], d[1]); sort2(c[2], c[3], d[2], d[3]); sort2(c[4], c[5], d[4], d[5]); sort2(c[6], c[7], d[6], d[7]);
            sort2(d[0], d[7], e[0], e[7]); sort2(d[1], d[6], e[1], e[6]); sort2(d[2], d[5], e[2], e[5]); sort2(d[3], d[4], e[3], e[4]);
            sort2(e[0], e[2], f[0], f[2]); sort2(e[1], e[3], f[1], f[3]); sort2(e[4], e[6], f[4], f[6]); sort2(e[5], e[7], f[5], f[7]);
            sort2(f[0], f[1], a[0], a[1]); sort2(f[2], f[3], a[2], a[3]); sort2(f[4], f[5], a[4], a[5]); sort2(f[6], f[7], a[6], a[7]);
        }
        Ответить
        • Немного быстрее, но там выигрыш идет из-за последней стадии (т.е. последние три строчки с sort2)
          // Вот эти вот три говнострочки
              sort2(a[0], a[1], b[0], b[1]); sort2(a[2], a[3], b[2], b[3]); sort2(a[4], a[5], b[4], b[5]); sort2(a[6], a[7], b[6], b[7]);
              sort2(b[0], b[3], c[0], c[3]); sort2(b[1], b[2], c[1], c[2]); sort2(b[4], b[7], c[4], c[7]); sort2(b[5], b[6], c[5], c[6]);
              sort2(c[0], c[1], d[0], d[1]); sort2(c[2], c[3], d[2], d[3]); sort2(c[4], c[5], d[4], d[5]); sort2(c[6], c[7], d[6], d[7]);
          // по сути просто делают четыре сортированных элемента, и еще четыре сортированных элемента.
          
          
          /// если заменить это на:
              sort2(a[0], a[1], b[0], b[1]); sort2(a[2], a[3], b[2], b[3]); sort2(a[4], a[5], b[4], b[5]); sort2(a[6], a[7], b[6], b[7]); // эта строка без изменений
              
              MERGE_2_4(b[0], b[1], b[2], b[3], d[0], d[1], d[2], d[3]);
              MERGE_2_4(b[4], b[5], b[6], b[7], d[4], d[5], d[6], d[7]);
          // то получается чуточку быстрее


          Если последнюю стадию улучшить (наанроллить) в моем варианте, можно быстрей перфоманс сделать.
          Ответить
          • Вообще, profile guided optimization (PGO) решает:
            [email protected]:~/prog/sort_shit$ gcc-7 -O3 -march=native -std=gnu++11 rand_benchmark.cpp  -lstdc++
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 401513026
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 405119209
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 400842337
            [email protected]:~/prog/sort_shit$ gcc-7 -O3 -march=native -std=gnu++11 -fprofile-generate rand_benchmark.cpp  -lstdc++
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 463633839
            [email protected]:~/prog/sort_shit$ gcc-7 -O3 -march=native -std=gnu++11 -fprofile-use -freorder-blocks-and-partition -fprofile-correction -Wcoverage-mismatch rand_benchmark.cpp -lstdc++
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 376823228
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 375864788
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 377222836



            Да, если с PGO оптимизировать обычный std::sort, он оба варианта уделывает по пирфомансу
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 140083097
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 139075303
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 139685936
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 139227202
            [email protected]:~/prog/sort_shit$ ./a.out 
            time = 138889191


            https://paste.debian.net/hidden/eadc947e/ - вот код для тестов, если интересно
            Ответить
            • Поправка - там был баг в заполнении байтиков из /dev/urandom, изза чего там много нулей в массиве было
              // было
                  ssize_t result = read(randfd, str, sizeof(str));
                  if (result < 0)
                  {
                    fprintf(stderr, "read err\n");
                    exit(-1);
                  }
              
              // стало
                  size_t randomDataLen = 0;
                  while (randomDataLen != sizeof(str) )
                  {
                    ssize_t result = read(randfd, (char *)str + randomDataLen, sizeof(str) - randomDataLen);
                    if (result < 0)
                    {
                      fprintf(stderr, "read err\n");
                      exit(-1);
                    }
                    randomDataLen += result;
                  }


              Теперь std::sort опять проигрывает, даже с PGO. Видимо этот std::sort по дизайну так запилен, чтоб частично сортированнные массивы досортировывать (досортировывать массивы из одних нулей - легко!), а если еще PGO использовать, то тогда вообще супер быстро получается.

              https://paste.debian.net/hidden/368b30a7/
              Ответить
        • Я провел еще дополнительные исследования. Чистая битонная сортировка (без вклиниваний MERGE_2_4) на clang++-6.0 работает существенно быстрее каких-либо других вариантов

          https://paste.debian.net/hidden/d6c6cd71/ тестовый код

          rm default.profdata default.profraw
          
          clang++-6.0 -O3 -fno-stack-protector -D_FORTIFY_SOURCE=0 -march=native -std=gnu++11 -fcoverage-mapping -fprofile-instr-generate rand_benchmark.cpp -lstdc++
          ./a.out
          llvm-profdata-6.0 merge -output=default.profdata default.profraw
          clang++-6.0 -O3 -march=native -fno-stack-protector -D_FORTIFY_SOURCE=0 -fprofile-instr-use=default.profdata -std=gnu++11 rand_benchmark.cpp -lstdc++
          ./a.out; ./a.out; ./a.out; ./a.out

          Вывод времени

          time = 154968303
          time = 149922928
          time = 151220900
          time = 150623575


          Для GCC-8 всё сильно медленней:
          gcc-8 -O3 -fno-stack-protector -D_FORTIFY_SOURCE=0 -march=native -std=gnu++11 -fprofile-generate rand_benchmark.cpp -lstdc++
          ./a.out
          gcc-8 -O3 -fno-stack-protector -D_FORTIFY_SOURCE=0 -march=native -std=gnu++11 -fprofile-use -freorder-blocks-and-partition -fprofile-correction -fbranch-target-load-optimize -fbranch-probabilities -Wcoverage-mismatch rand_benchmark.cpp -lstdc++
          ./a.out; ./a.out; ./a.out; ./a.out;


          time = 381412656
          time = 381636722
          time = 381310683
          time = 379839114
          Ответить
          • Чтоб докопаться до причин такой разницы, можно сделать
            void __attribute__ ((noinline)) sort8_b(uint64_t a[8])

            (тогда можно будет увидеть саму функцию в ненаанролленом виде).

            И что же мы видим в случае clang?
            _Z7sort8_bPm:                           # @_Z7sort8_bPm
            	.cfi_startproc
            # %bb.0:
            	pushq	%r15
            	.cfi_def_cfa_offset 16
            	pushq	%r14
            	.cfi_def_cfa_offset 24
            	pushq	%rbx
            	.cfi_def_cfa_offset 32
            	.cfi_offset %rbx, -32
            	.cfi_offset %r14, -24
            	.cfi_offset %r15, -16
            	movq	(%rdi), %rax
            	movq	8(%rdi), %rcx
            	cmpq	%rcx, %rax
            	movq	%rcx, %r9
            	cmovbq	%rax, %r9
            	cmovbq	%rcx, %rax
            	movq	16(%rdi), %rsi
            	movq	24(%rdi), %rcx
            	cmpq	%rcx, %rsi
            	movq	%rcx, %r8
            	cmovbq	%rsi, %r8
            	cmovbq	%rcx, %rsi
            	movq	32(%rdi), %r10
            	movq	40(%rdi), %rcx
            	cmpq	%rcx, %r10
            	movq	%rcx, %r11
            	cmovbq	%r10, %r11
            	cmovbq	%rcx, %r10
            	movq	48(%rdi), %rdx
            	movq	56(%rdi), %rbx
            	cmpq	%rbx, %rdx
            	movq	%rbx, %rcx
            	cmovbq	%rdx, %rcx
            	cmovbq	%rbx, %rdx
            	cmpq	%rsi, %r9
            	movq	%rsi, %rbx
            	cmovbq	%r9, %rbx
            	cmovaeq	%r9, %rsi
            	cmpq	%r8, %rax

            куча сравнений и условных мувов.


            Что же касается GCC:
            _Z7sort8_bPm:
            .LFB2309:
            	.cfi_startproc
            	movq	8(%rdi), %rsi
            	pushq	%rbx
            	.cfi_def_cfa_offset 16
            	.cfi_offset 3, -16
            	movq	(%rdi), %r11
            	cmpq	%r11, %rsi
            	ja	.L83
            	movq	%r11, %rax
            	movq	%rsi, %r11
            	movq	%rax, %rsi
            .L83:
            	movq	24(%rdi), %rcx
            	movq	16(%rdi), %r10
            	cmpq	%r10, %rcx
            	ja	.L84
            	movq	%r10, %rdx
            	movq	%rcx, %r10
            	movq	%rdx, %rcx
            .L84:
            	movq	40(%rdi), %rdx
            	movq	32(%rdi), %r9
            	cmpq	%r9, %rdx
            	ja	.L85
            	movq	%r9, %rbx
            	movq	%rdx, %r9
            	movq	%rbx, %rdx
            .L85:
            	movq	56(%rdi), %rax
            	movq	48(%rdi), %r8
            	cmpq	%r8, %rax
            	ja	.L86
            	movq	%r8, %rbx
            	movq	%rax, %r8
            	movq	%rbx, %rax
            .L86:
            	cmpq	%r11, %rcx
            	ja	.L87
            	movq	%r11, %rbx
            	movq	%rcx, %r11
            	movq	%rbx, %rcx
            .L87:
            	cmpq	%rsi, %r10
            	ja	.L88
            	movq	%rsi, %rbx
            	movq	%r10, %rsi
            	movq	%rbx, %r10
            .L88:

            Мы видим кучу меток и условных переходов, тут явно какой-то косяк компилятора. Надо будет в багзиллу GCC ченить накатать по этому поводу.
            Ответить
            • К вопросу об эффективности cmov в сравнении с условными переходами: https://github.com/xiadz/cmov
              Ответить
              • Кстати, а у тебя avx-512 есть?
                Ответить
                • Нет, у меня вообще тут довольно старый процессор Intel Core2 Quad Q9300 @ 2.50GHz и нет никаких особых причин переходить на что-то более новое (учитывая что всякие там мелтдауны аппаратно так и не пофиксили).
                  Ответить
                  • А какое там SSE?
                    Ответить
                    • flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl cpuid aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 lahf_lm pti tpr_shadow vnmi flexpriority dtherm
                      Ответить
                      • 4.1 получается? Ну тогда min/max уже должны быть. Но в регистр всего 2 числа входит, сложно будет конкурировать с cmp + cmov.
                        Ответить
                      • > ssse3
                        sssssssssse3
                        Ответить
                • Можешь на своем процессоре эти тесты прогнать со своими сортировками, если у тебя этот avx-512 есть. Можно еще под какой-нибудь андроид скомпилировать и там запустить на ARM. Или на роутере с OpenWRT.
                  Ответить
                  • Под восьмибитный AVR.

                    Кстати можно на stm'ке с NEONом попробовать.
                    Ответить
                    • Лучше под GA144.

                      http://www.greenarraychips.com/home/documents/greg/PB001-100503-GA144-1-10.pdf
                      Ответить
                      • >> This very powerful and versatile chip consists of an 18x8 array of architecturally identical, independent, complete F18A computers

                        ... можно срать в два унитаза в сорок тысяч раз быстрей.
                        Ответить
              • Надо ещё попробовать векторное расширение gcc. Может быть с ним что-то интересное получится. Там интринсики руками ебашить не надо.
                Ответить
                • Прикольно, инструкции для min и max генерить умеет.
                  Ответить
                  • Броманд, ты юзал eBPF? Я верно понимаю что ими можно профилить не только сеть, но и что угодно теперь? Это вместо dtrace (на bsd/system v) и EWT (на винде)?
                    Ответить
                    • :
                      https://lwn.net/Articles/740157/
                      там еще файрволы можно делать в юзерспейсе оказывается

                      а вот этот чел сделал мой день

                      Next step: JavaScript in the kernel.
                      /me runs and hides.
                      Ответить
                    • Не, не юзал. Это вроде и было фаерволом, а потом обобщили...
                      Ответить
                      • Изначально berkely packet filter это был такой интерфейс чтобы фреймы канальном уровне тягать по опреденному фильтру, tcpdump им пользовался.

                        Ты описывал фильтры на спец языке, который потом в ядре выполнялся (ну как aml например).

                        А в лялихе потом додумались его юзать и для файра и для трейсинга
                        Ответить
                  • Блядь, min и max по-отдельности получаются. А стоит в одной функции их оба заюзать - вместо двух няшных инструкций получается какая-то портянка из хуйни.
                    Ответить
                • В общем, непредсказуемая и неконтролируемая хуйня это векторное расширение, придётся на интринсиках ебашить...

                  С 256-битными интринсиками получилось вроде красиво (каждый сортирующий слой из cmpgt + blend + blend и между ними небольшие перестановки по 1-2 инструкции), но почему-то на треть медленнее невекторизованной битонки. Неужели AVX такой тормозной?
                  Ответить
                  • И со 128-битными тоже не прокатило :(
                    Ответить
                    • Кажется придумал, как на 128-битных кучу времени отыграть... Но подушка уже зовёт.
                      Ответить
            • А тернарником gcc не получится уломать на cmov?

              oa = a < b ? a : b;
              ob = a < b ? b : a;
              Ответить
              • Получится только для GCC из транка: https://godbolt.org/z/nTiVYq
                Ответить
                • А со всякими -march, -mtune, -O3 и прочими параметрами?
                  Ответить
                  • Это тут не влияет. Можешь сам на godbolt.org перебирать опции, если не лень
                    Ответить
                • cmovу больше лет, чем некоторым говнокодерам тут
                  почему его только сейчас заметили?
                  Ответить
                  • Потому что он не поддерживался на «Петух MMX».

                    Серьёзно, производители кококонпеляторов знают про «SSE» и «AVX», но игнорируют «CMOV»?
                    Ответить
                    • ну так и потоковые ОИМД расширения петуха не работают на "петух многоносительныерасширения"
                      Ответить
                  • Ну и хуй с ним, инструкций много, давайте я начну возмущаться что никто не замечает xlat.
                    Ответить
                    • Давайте! Такая удобная инструкция для перекодирования.

                      Хотя с другой стороны, в 32- и 64-битном режимах с появлением s-i-b (scale-index-base) она и вправду стала не нужна.
                      Ответить
                    • >>инструкцый много
                      это правда
                      x86 та еще помоечка:)

                      Я знаю кое-кого кто даже debug registers не использует до сих пор
                      Ответить
                      • Раздражает некокококонсистентность.

                        То ли дело «PDP-11», у которого любую инструкцию можно было использовать с любым набором регистров (было всего несколько исключений для спецрегистров).

                        Даже «ARM» кококококонсистентнее, потому что у него предикаты есть у всех инструкций, а не только у «CMOV».
                        Ответить
                        • некококок у хэ86 связана с долгой говноисторией

                          Всё равнои ли поздно порастает пиздой: языки, фреймворки, операционные системы, программы, и ISA процессоров

                          потому раз в 15 лет надо всё обссыкать, сжигать и начинать с ноля.
                          Ну вот Интел попробовал Итаниум, но пидарасы с софтом 1989 года не дали ему этого сделать
                          Ответить
                          • Был бы софт попенсорсным, его бы перекокококонпелировали. Именно поэтому я против «closed source».
                            Ответить
                            • ну тут тоже не все прсото.

                              Наример в BSD принято собирать софт для конкретной версии ОС и потому они могут позволить себе ломать и ABI ядра и что угодно.


                              в линуксе так не делают (торвальдс больно бьет по рукам за слом abi), так что там тоже много легаси говна

                              но они его депрекейтят по-тихоньку
                              Ответить
              • торвальдс проклял cmov, кстати
                https://yarchive.net/comp/linux/cmov.html
                Ответить
                • А «ARM» и «Итаниум» с их предикатами он случайно не проклял?
                  Ответить
                  • Итаниум умер сам собой, чего его проклянать?

                    ARM Линусу похуй я думаю, он спец по x86 больше.
                    Ответить
                • Кунилинус Тролльвальдс много чего проклял. Мне кажецца, что он какой-нибудь колдун.
                  Ответить
                  • керел дебагер например он проклял
                    но потом прогнулся
                    Ответить
                    • Простите, я слушал лекцию не сначала. Что там прогнулось?
                      Ответить
                      • сначала ты такой
                        http://lwn.net/2000/0914/a/lt-debugger.php3

                        а потом такой
                        https://www.kernel.org/doc/html/v4.18/dev-tools/kgdb.html
                        Ответить
                        • Именно поэтому я за "kgb".
                          Ответить
                          • а я за "fsb"
                            правда, она уже не нужна с тех пор как MCH отменили

                            Кстати, в некоторых ОС керлендебагеров так и нет, и ничо: живут как-то


                            Зато вот в винде он был уже очень давно, да какой няшный
                            Ответить
                            • >> с тех пор как MCH отменили

                              Погуглил... Я проспал появление «Моста Песочка» и «Ускоренной единицы обработки».
                              Ответить
                              • в смысле ты до сих пор думал что есть выделенный концентратор соединения памяти?

                                может быть до сих пор называл его северным мостом?
                                Ответить
                                • Я его называл «Кукареку». Мой петушиный мозг не вмещает такое количество терминов.
                                  Ответить
                                  • Кстати, котролер памяти, корневой комплекс шины интерфейса перефирийного подключения и прочие радости уехали в ЦПУ еще в Нехалеме (первый ядро).

                                    А песочный мостик это уже следующее коколение.

                                    У нехалема были еще всякие цветочные поля, какие-то там леса итд


                                    а песчаный мостик превратился потом в ивовый мостик

                                    А сейчас у нас эпоха озер: у меня есть небесное озеро, например
                                    Ответить
                                    • У людей совсем не стало фантазии, то ли дело раньше процы называли: 4004, 4040, 8008, 8080, 8086, 8088, 80186, 80188, 80286, 80386, 80486, 6800, 68000.
                                      Ответить
                                      • Нужно найти лишние числа в последовательности?

                                        6800 и 68000.
                                        Ответить
                                      • в СССРе там еще буквы были
                                        НЦ-8020 например


                                        Кста, когда интел стали клонировать он решит запатентоваться.
                                        И вот когда оказалось что патентовать цЫфры нельзя, он назвал проц pentium, хуй знает что это значит
                                        Ответить
                                        • В СССР были КР580ВМ80А (клон 8080), К1810ВМ86 (клон 8086) и т. п.

                                          Были серии с укороченным названием T34, Т36, Т37 (вместо длинных КР580, К1810).

                                          Были микропроцессоры с буквами ВП, ВЕ, ИК, ХЛ вместо ВМ.

                                          У «Эльбрусов» и сейчас такие наименования: 1891ВМ10Я, 1891ВМ11Я.
                                          Ответить
                                          • ебанистические названия до сих пор есть у оперативок
                                            там кодируется много чего
                                            https://www.kingston.com/ru/memory/valueram/valueram_decoder
                                            Ответить
                                            • > ебанистические названия
                                              Да почти у всех чипов ебанистические названия, на самом деле. Тут скорее пекашные процы - исключение.
                                              Ответить
                                        • У IBM ещё были мейнфреймы 701, 702, 704, 7090 и пр.
                                          Ответить
                                          • и OS 360:)
                                            Ответить
                                            • А ещё DB/2 и PL/1. Очень удобно: видишь такие номера –— сразу понимаешь, кто разработчик.
                                              Ответить
                                              • Я придумал идею хостинга для сайтов:
                                                • Операционная система: OS/2.
                                                • Интерпретатор скриптов: PL/1.
                                                • Система управления базами данных: DB/2.
                                                Ответить
                                              • очно,оно же OS/360
                                                OS/2 и PS/2.

                                                А есть продут [smthng]/0 ?
                                                Ответить
                                                • > А есть продут [smthng]/0 ?
                                                  PL/0 есть. Вообще у PL/1 много диалектов.
                                                  Ответить
                                                  • Были диалекты с буквами вместо цифр после косой черты.
                                                    Ответить
                                                  • > PL/0

                                                    Programming Language for Division by Zero?
                                                    Ответить
                                                    • Его реализция под x86 активно использует обработку соответствующего прерывария/Faultа
                                                      Ответить
                                                      • При желании можно инструкцию bound использовать для API:
                                                        http://govnokod.ru/24481#comment420978

                                                        http://govnokod.xyz/_24481/#comment-376917
                                                        Ответить
                                                  • почему я читаю про PL/0, а вижу паскаль?
                                                    VAR x, squ;
                                                    
                                                    PROCEDURE square;
                                                    BEGIN
                                                       squ:= x * x
                                                    END;
                                                    
                                                    BEGIN
                                                       x := 1;
                                                       WHILE x <= 10 DO
                                                       BEGIN
                                                          CALL square;
                                                          ! squ; {кроме как тут}
                                                          x := x + 1
                                                       END
                                                    END.
                                                    Ответить
                                                    • Ну ещё вызов процедур и функций отличается от Паскаля: CALL square;

                                                      >> In the third and last edition of his book on compiler construction, Wirth replaced PL/0 with Oberon-0.

                                                      Интересно, существовала ли Модула-0 или Ада-0.
                                                      Ответить
                                                      • нумерация с ноля
                                                        Ответить
                                                      • Жалко все таки что виртовские языки погибли, а выжило одно пэ аш пэ
                                                        Ответить
                                                    • > educational programming language
                                                      Ох, а то я уж подумал, что на таком настоящие программы писали.
                                                      Современные школьники наверно уже и языки без замыканий считают говном.
                                                      Ответить
                                                      • языки, не являющиеся джаваскриптом школьники считают говном))
                                                        Ответить
                                                      • На PL/1 целую Multics написали, правда он гораздо сложнее чем PL/0.
                                                        Ответить
                                                        • мне кажется что ядреную часть мультикс так-то писали на асме
                                                          pl/1 там был только для юзерспейса

                                                          мысль писать кернелспейс на ЯПе выскоуровня родилась вперавые у керниганов с ричами
                                                          Ответить
                                                        • Там хотя бы аргументы функций есть, в отличие от PL/0.
                                                          Ответить
                                                          • Интересно, если я скажу тебе что у функций бывают формальные параметры, а аргументы им передают при вызове, то ты разразишься постом про то, что аргумент и параметр это одно и тоже?
                                                            Ответить
                                                            • Может, когда-нибудь потом.
                                                              Слишком очевидно, что это одно и то же, названное разными словами. Аргумент - это фактический параметр.
                                                              Тонкости нужны только в лямбда-исчислении и при построении трансляторов.
                                                              Ответить
                                                              • Кстати, как там в твоем любимом языке с имеованными параметрами?
                                                                Ответить
                                                                • По умолчанию нет, но можно фигурные скобки использовать. Для этого в новых версиях даже синтаксического сахарку отсыпали.
                                                                  Ответить
                                                                  • понятно. Той же дорожкой ходите что и руби. И перл тоже туда шел, да не дошел.
                                                                    Ответить
                                                                    • Там теперь параметры по умолчанию, раскрытие объектов и массивов при передаче в функцию и при принятии внутри.
                                                                      function f(a=0, {x=1, y=2} = {}, ...other) {
                                                                        return [1, 2, a + x + y + other.reduce((x,y)=>x+y)];
                                                                      }
                                                                      
                                                                      var [x, y, z] = f(...[1, {x:10, y:0}, 2], ...[3, 4]);
                                                                      
                                                                      // x == 1
                                                                      // y == 2
                                                                      // z == 20
                                                                      Ответить
                                                                      • >var [x, y, z] =
                                                                        ух ты, такая штука есть и в питоне и в руби и в луа и даже в перле в енкотором смысле

                                                                        теперь вот и в JS
                                                                        Ответить
                                                                        • Даже в кресты завезли (семнадцатые): https://wandbox.org/permlink/rE38NBBcSXJhFSmp
                                                                          Ответить
                                                                          • Короче, нет только в джаве
                                                                            Ответить
                                                                          • Красота. А вкладывать и обрезать хвосты можно?
                                                                            var [a, [b, c], ...def] = ["a", "bc", "d", "ef"];
                                                                            Ответить
                                                                            • my $a;
                                                                              my $b;
                                                                              my $c;
                                                                              
                                                                              ($a, $b, $c) = (1, (2, 3));
                                                                              
                                                                              print $a + $b - $c; #0 потому што a b c есть 1 2 3


                                                                              причем скобки можно как угодно расставлять

                                                                              именно по этому я за перл
                                                                              Ответить
                                                                              • > причем скобки можно как угодно расставлять
                                                                                А это уже сомнительная фича.
                                                                                Ну то есть хорошо бы два режима - "скалярный", когда она включена и "векторный", когда выключена, по умолчанию - "векторный"

                                                                                (Это я исходя из опыта работы с JS, где можно в переменной хранить сначала число, потом - после усложнения логики программы - массив или объект, что вызовет глюки, если "скалярный" режим работает по умолчанию)
                                                                                Ответить
                                                                            • Не-а, Комитет не осилил (но ходят слухи, что в следующих Стандартах таки добавят вложенные биндинги… надеюсь, к тому моменту мы ещё живы будем). Зато вот, кстати, биндинг структур подвезли:
                                                                              struct X {
                                                                                  int x = 1;
                                                                                  float y = 12.2f;
                                                                                  std::string hello = "Hello";
                                                                              };
                                                                              
                                                                              X getShit()
                                                                              {
                                                                                  return {};
                                                                              }
                                                                              
                                                                              int main()
                                                                              {
                                                                                  auto[a, b, c] = getShit();
                                                                                  std::cout << a << ' ' << b << ' ' << c << std::endl;
                                                                              
                                                                                  return EXIT_SUCCESS;
                                                                              }

                                                                              https://wandbox.org/permlink/IxOATTwP2gBcbNwE

                                                                              А ещё есть прикольный «std::tie()», но он ебанутый.
                                                                              Ответить
                                                    • Потому что Вирьт ;)
                                                      Ответить
                                      • > фантазии
                                        То ли дело EP4CE22F17C6N.
                                        Ответить
                                        • {74246bfc-4c96-11d0-abef-0020af6b0b7a}
                                          Ответить
                                          • когда через bcdedit копируешь bootloader запись, он изменяет кусочек юида где-то в середине

                                            например, у меня есть записи
                                            {da36df39-357e-11e5-be3f-c86000df5fdd}
                                            {da36df41-357e-11e5-be3f-c86000df5fdd}


                                            Это разные записи, если кто не заметил. Очень удоьно
                                            Ответить
                                        • Ты всю начинку циклоняши наизусть помнишь?
                                          Ответить
                                          • > всю начинку циклоняши
                                            А что там помнить? LUT'ы, регистры, умножители, память, PLL'ки, I/O блоки. Она по структуре проще многих контроллеров, на самом деле.
                                            Ответить
                                            • а reservation stationов в такой мелочи нету?
                                              Ответить
                                              • > reservation station
                                                Это ж не проц... Напишешь - будут (если влезут, конечно).
                                                Ответить
                                                • кто не проц?
                                                  как н проц?
                                                  о чем ты/
                                                  Ответить
                                                  • EP4CE22F17C6N ака Циклоняшка - не проц.
                                                    Ответить
                                                    • а) я понял) это fpga типа, болванка для проца или SoC, и её ты сам программируешь.
                                                      Ответить
                                      • Из истории 8008: Noyce said it was an intriguing idea, and that Intel could do it, but it would be a dumb move. He said that if you have a computer chip, you can only sell one chip per computer, while with memory, you can sell hundreds of chips per computer.
                                        Ответить
                                        • много воды утекло с тех пор
                                          и DRAM перестали делать
                                          Ответить
                                        • много воды утекло с тех пор
                                          и DRAM перестали делать
                                          Ответить
                        • именно поэтому я за «DTrace»
                          Ответить
                          • http://dtrace.org/blogs/about/dtracepony/ у них там тоже пониебство головного мозга. Видать от крестоблядей подхватили https://govnokod.ru/25148

                            То ли дело SoftICE (RIP)
                            Ответить
                            • софтайс же дебагер был а не профайлер, или путаю?
                              Ответить
                              • DTrace это не совсем дебаггер, но кроме профайлера это еще и трассировщик, что уже приближает его по функционалу к отладчикам (тот же gdb тоже трассировать умеет, бектрейсы можно смотреть). Ну и в Soft-ICE тоже всякие бектрейсы можно, трассировать всякую фигню.
                                Ответить
                              • Ну вообще это больше к roman-kashitsyn вопрос, почему он DTrace приплел к kgdb, ведь через DTrace никаких брейкпоинтов например ставить не получится, и пошагово что-то там выполнять
                                Ответить
                          • http://govnokod.xyz/_25307/#comment-423082
                            Ответить
              • Во, такой вариант вроде оптимизируется через movcc в не самых новых транковых версияx GCC https://godbolt.org/z/DinIiH

                void sort2_128( unsigned __int128 a, unsigned __int128& oa)
                {
                  uint64_t a_l = a;
                  uint64_t a_h = a >> (unsigned __int128)64;
                  if (a_l > a_h)
                  {
                      oa = a;
                  }
                  else
                  {
                      a = a_h;
                      oa = (unsigned __int128)a_l << (unsigned __int128)64;
                      oa |= a;
                  }
                }


                sort2_128(unsigned __int128, unsigned __int128&):
                        cmp     rdi, rsi
                        mov     rax, rsi
                        cmova   rax, rdi
                        cmovbe  rsi, rdi
                        mov     QWORD PTR [rdx], rax
                        mov     QWORD PTR [rdx+8], rsi
                        ret
                Ответить
                • Еще забавно, что clang (даже из транка) на этот код как раз генерирует джампы:
                  sort2_128(unsigned __int128, unsigned __int128&):                        # @sort2_128(unsigned __int128, unsigned __int128&)
                          cmp     rdi, rsi
                          ja      .LBB2_2
                          mov     rax, rdi
                          mov     rdi, rsi
                          mov     rsi, rax
                  .LBB2_2:
                          mov     qword ptr [rdx], rdi
                          mov     qword ptr [rdx + 8], rsi
                          ret
                  Ответить
              • кстати, если переписать на Си (без заедушной крестоговняной передаче по ссылке), и скомпилировать как Си, то cmov-ы генерируются для тернатрой версии и более старыми версиями GCC
                https://godbolt.org/z/yLGWmR - использована опция "-x c" - если ее убрать, cmov-ы пропадут. Поэтому я за Си.
                Ответить
    • Вообще, наибыстрейший в среднем алгоритм сортировки, если сортируемые данные это чистый рандом, зависит еще от того, как соотносится время, в среднем затрачиваемое на сравнение с временем, затрачиваемым на перестановку элементов. Ну т.е. если надо сортировать какой-нибудь гипотетический uint1024_t, процедуру сравнения двух таких чисел можно сделать через последовательное сравнение 16-ти 64-битных uint64_t (т.к. 1024/64 = 16)
      int cmp_uint1024_t(uint64_t val1024_a[16], uint64_t val1024_b[16])
      {
        for (size_t i = 0; i < 16; i++)
        {
          if (val1024_a[i] < val1024_b[i])
          {
            return B_GREATER_THAN_A;
          }
          else if (val1024_a[i] > val1024_b[i])
          {
            return A_GREATER_THAN_B;
          }
        }
        return A_EQUAL_B; // или тут можно B_GREATER_THAN_A вернуть если в этом случае свап не делается
      }


      на случайных данных будет оччень малая вероятность, что на первом же 64-битном куске оба числа будут одинаковы (если быть точным, вероятность эта равна 1/18446744073709551616 - вероятность случайно угадать 64-битное число)

      а процедура обмена двух uint1024_t уже будет достаточно дорогой. Но можно не менять сами uint1024_t, а хранить некий вспомогательный массив индексов
      void sort2(uint64_t val1024_arr[][16], uint8_t index_a[1], uint8_t index_b[1])
      {
        int cmp = cmp_uint1024_t( arr[ index_a[0] ], arr[ index_b[0] ] )
        if ((cmp == B_GREATER_THAN_A) || (cmp == A_EQUAL_B))
        {
          return;
        }
        else
        {
          // swap this shit;
          uint8_t tmp;
          tmp = a[0];
          a[0] = b[0];
          b[0] = tmp;
        }
      }

      А потом уже в конце можно пораспихивать все эти массивчики через этот говномассив с перестановками, но если мы сортируем большой массив (а не кусочками по 8 штук) то у нас от прыганья по этим индексам будет промахи кэша, в общем тут много чего можно понапридумывать с этим говном
      Ответить

    Добавить комментарий