DIV! Ryzen 3600X VS Xeon 5450

Тема в разделе "WASM.ASSEMBLER", создана пользователем Intro, 31 июл 2023.

  1. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.125
    енто чо ли https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html#inpage-nav-3 ? :)
    --- Сообщение объединено, 6 авг 2023 ---
    однако, во многопоточке такая радость не очень-то и работает == единственное, что порой может тащить, - это спекулятивные вычисления. тч по-хорошему в кэш лучше кидать лишь константы и переменные с низкой динамикой.
     
    Marylin нравится это.
  2. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    128
    "Hardware Prefetch" не имеет никакого отношения к внешней шине ОЗУ - это сугубо внутренняя фишка процессора. Когда в MSR.1A4 бит(2) DCU=0, то за каждый такт ЦП, из L1d читается сразу по 2 линии (128-байт), вместо одной. Эти данные сливаются из L1d прямо в исполняющие устройства процессора "Execution Unit" (ALU или FPU, в зависимости от инструкции), а не из ОЗУ в кэш. В этом-же MSR имеется и бит(3) DCU-IP, который на основе указателя RIP предыдущих чтений делает прогноз, а нужно-ли вообще осуществлять предвыборку доп.строк из L1d. Софт "PC Wizard" предоставляет наиболее полную инфу о девейсах, в том числе и кэшах:

    L1.png
     
    Mikl___ нравится это.
  3. R81...

    R81... Active Member

    Публикаций:
    0
    Регистрация:
    1 фев 2020
    Сообщения:
    142
  4. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    128
    Нет.. именно последовательно. (ну или да, раздельно)
    Разрядность шины-данных одного чипа 8-бит, и при последовательном их соединении получаем 64-бита. Данные записываются в чипы так-же последовательно, например строка из 8-ми байт запишется не в один чип, а по байту в каждый.
     
  5. R81...

    R81... Active Member

    Публикаций:
    0
    Регистрация:
    1 фев 2020
    Сообщения:
    142
    Ни чего не понятно - какой "четырёхтомник", зачем здесь Tor?
    По ссылке UbIvItS-а ветки web.archive.org переводят на скачивание без Vol.4, т.е. 9-томник - 325462-sdm-vol-1-2abcd-3abcd.pdf (25 443 559),
    который по рекомендации Indy_ уже давно скачивали.
    А так же ВНИМАНИЕ сами разбирайтесь за какое число.
    скачивается 325462-sdm-vol-1-2abcd-3abcd.pdf (52 916 900) -
    ошибка в названии, должен называться ...-vol-1-2abcd-3abcd-4.pdf 10-томник!
    Или имелись ввиду другие документы?
    --- Сообщение объединено, 6 авг 2023 ---
    Marylin, электрический ток идет последовательно или параллельно - к моему сожалению наши определения разошлись.
    --- Сообщение объединено, 6 авг 2023 ---
    P.S. Посмотрел внутрь - все 10-томники, от Indy_ тоже (26 220 267) и страниц больше 5038!
     
  6. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    128
    Разводка по чипам идёт последовательно 8х8 (на плате модуля),
    а сигналы по этой составной/внешней шине передаются конечно-же параллельным интерфейсом.
     
    Mikl___ нравится это.
  7. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.125
    ежли кому, прям очень надобно :)
     

    Вложения:

  8. algent

    algent Member

    Публикаций:
    0
    Регистрация:
    11 апр 2018
    Сообщения:
    101
    Забавно, а сейчас через Тор получилось зайти. Но скачать ничего не смог.
    И фиг с ним. Похоже у меня тот пдф, который зовут "Combined Volume Set of Intel® 64 and IA-32 Architectures Software Developer’s Manuals". 26 192 768 bytes, 5052 страницы. Но я глядя на bookmarks, думал что это "четырёхтомник". Похоже в 10 томах тоже самое. В нём есть секция - 1.4 RELATED LITERATURE - я там и был дезинформирован.
    Нет. Кэш это как деньги, в высшей степени ликвидный ресурс. В любую секунду - сразу в дело. В отличии от недвиги, акций, золота и даже самой крутой банковской карты. К кэшу надо относиться как к регистрам, не держать там ничего лишнего. То что будет читаться в ближайшие несколько тысяч чтений. Не допускать "cache pollution". Всё что не понадобиться, сохранять командами MOVNTI, MOVNTQ, MOVNTDQ, MOVNTPS, and MOVNTPD.
    Имхо, вы куда-то спешили, поэтому напутали. Я сам довольно рассеян, мне это, увы, знакомо.
    L1 - это нижний уровень, ниже только "крохотные" регистры, по 8 байт. Куда эти 128 байт девать? Да и он достаточно быстр, не нужно заморачиваться с шиной шириной 1024(8*128)бит.
    Там я про DCU не писал. Я имел в виду L2 Hardware Prefetcher

    upload_2023-8-7_2-10-58.png
    Стр. 4640. У Атома нет L3, над L2 сразу ОЗУ.



    Имхо, лучше всегда качать с сайта производителя.
     
    Marylin нравится это.
  9. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    128
    Блин давно читал доки на тему DCU, и то подиагонали.
    Сейчас ознакомился подробней, и оказывается сорян.. префетчеры читают из LLC (Last-Level-Cache) в L1d и если промах, то лезут в ОЗУ. Описание есть в доке Интела "IA64 Architectures Optimization Manual" (см.скрепку). Имеются три вида предвыборки: софт, хард и IP. Но теперь появились вопросы к практической реализации аппаратной фишки, и если следовать логике, то это просто разрекламированная хрень. Немного мыслей на этот счёт..
    -------------------------------
    Если бит[DCU] в MSR включает аппаратный префетч из ОЗУ, то сама ОЗУ должна поддерживать этот режим. Ведь как работает тот-же "BurstLength"? Чтобы организовать цикл чтения х8, DRAM-строку удерживают открытой регистры-защёлки в логике самих чипов памяти (#RAS активен всего такт и отпускается), а контроллёр по таймингам из SPD лишь посылает управляющие команды. На схеме ниже BL=2, размер пакета =4 байта (вместо 8, 64-бит). Контроллёр даже не дожидается окончания чтения первого пакета данных, и чз несколько тактов сразу выставляет адрес сл.столбца, который чип сохраняет в своём буфере декодера. Cигнал WE#=1, значит это чтение, а не запись (инверсный WriteEnable):

    Cycle.png

    Все характеристики своего модуля производитель зашивает в SPD, однако формат данных в SPD для DDR2 отличается от DDR3, а последняя от DDR4. Модули DDR2 применялись в 2-хабовой архитектуре чипсетов ICH+MCH, поэтому в их SPD имеется байт(16) с поддерживаемыми значениями BL=4 или 8. Но с приходом PCH память стала DDR3, и BL аппаратно выставили в 8. Теперь в спеках SPD.DDR3(4) нет уже поля BL. https://simmtester.com/News/Publications/2

    8001.png

    Таким образом, чтобы реализовать "Hardware Prefetch" для ОЗУ, нужно чтобы логика чипов могла удерживать строку открытой на время BL*2. То-есть фактически чип должен уметь BL=16. Завод обязательно прописал-бы свойство DCU в паспорте SPD модулей, но его нет ни в одной из спек SPD.DDRx.

    Тогда каким ещё способом можно тянуть из ОЗУ сразу по 128-байт? Остаётся вариант, когда по окончании первой транзакации в 64-байт, контроллёр тут-же запрашивает вторую. Но это новая серия фильма, и такой алго никак нельзя назвать аппаратно-эффективным Hardware, поскольку в буфере запросов контроллёра и так очередь как до луны. Немного спасает ситуацию 2-канальный режим памяти, при котором чтение происходит параллельно во-времени. Но две линии с последовательными адресами в разных модулях DDR, это скорее исключение, чем правило. В любом случае, имхо лучше иметь хоть и кривую фишку, чем никакой - есть "Hardware Prefetch", ну и хорошо.
     

    Вложения:

    Последнее редактирование: 7 авг 2023
    algent и Mikl___ нравится это.
  10. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.125
    когда в системе крутиться 100500 процессов и каждый норовит подгрузить свою хрень - да, весьма ликвидный (но при этом вероятность успешной подгрузки именно констант акь раз-таки растёт, пч константы хорошо шарятся + они и для спекулятивки просто прекрасно заходят); другое дело, когда имеет место быть сугубо реалтайм - вот тогда действительно в кэш можно пихать варики даже с довольно высокими уровнями изменчивости. :)
    --- Сообщение объединено, 7 авг 2023 ---
    обычно рекламных целей ради описывают некие максималки, кои требуют акь минимум повышенных тактовых частот и главное - чтоб звёзды дюже фаворно.. хотя при использование юникернов из жестянок можно действительно хорошо тащить скорость.
     
    Marylin нравится это.
  11. algent

    algent Member

    Публикаций:
    0
    Регистрация:
    11 апр 2018
    Сообщения:
    101
    О, за май 2020, спасибо, у меня "четырёхтомник" за ту же дату. Вдруг кому старые версии (2015, 2016) понадобятся могу выложить.
    Залез на сайт Микрона и скачал первую попавшуюся:
    Automotive DDR4 SDRAM MT40A512M8, MT40A256M16.
    https://media-www.micron.com/-/medi...dram.pdf?rev=b8d7463ccbb44cad81a0e73712e0c30e
    Куча изменений, по сравнению со старой памятью, нет одиночных RW, нет full-page burst(256 R или W). Но вот на 200 странице:
    Figure 130: Consecutive READ (BL8) with 1tCK Preamble in Different Bank Group
    Читается 16 чтений, без потерь тактов, но вторые 8, из другого банка. Фиг знает. Физически банк другой. Но что мешает считать данные из 2х банков(да хоть из 16), как единую последовательность... Главное помнить об этом, когда пишем. Ну это надо тратить время, чтобы разобраться подробнее...
     

    Вложения:

    Последнее редактирование: 8 авг 2023
  12. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    563
    Переделал код, алгоритм Решето Аткина, взял тут https://ru.wikipedia.org/wiki/Решето_Аткина
    Оптимизировал как смог, деление заменил обратным умножение.
    Код (ASM):
    1.  
    2. ;; простые числа v0.05
    3. .386
    4. .model flat, stdcall
    5. option casemap:none
    6. include \masm32\include\windows.inc
    7. include \masm32\include\kernel32.inc
    8. includelib \masm32\lib\kernel32.lib
    9. include msvcrt.inc
    10. include macros.asm
    11. .data?
    12. CountDIV        dword ?
    13. ;is_prime       byte 10000000 dup (?)   ;bool   is_prime[1001];
    14. .code
    15. align_proc
    16. CountPrimes proc (dword) uses esi edi ebx limit:dword
    17. local i:dword, sqr_lim:dword, pIsPrime:ptr
    18.     ;;mov       m12, 12, m12:dword
    19.     ;// Инициализация решета
    20. ;   sqr_lim = (int)sqrt((long double)limit);
    21.     fild    limit
    22.     fsqrt
    23.     fistp   sqr_lim
    24.     mov     pIsPrime, GlobalAlloc(GPTR, limit)
    25.     ASSUME  eax:ptr byte
    26. ;   .for (edx = 0: edx <= limit: edx++)
    27. ;       mov     is_prime[edx], false
    28. ;   .endfor
    29.     mov     [eax][2], true
    30.     mov     [eax][3], true
    31.     ;// Предположительно простые — это целые с нечётным числом
    32.     ;// представлений в данных квадратных формах.
    33.     ;// x2 и y2 — это квадраты i и j (оптимизация).
    34.     xor     esi, esi    ;x2:esi = 0
    35.     .for (i = 1, eax=i: eax<=sqr_lim: i++, eax=i)
    36.         ;x2 += 2 * i - 1
    37.         lea     esi, [esi+eax*2-1]
    38.         xor     edi, edi    ;y2:edi = 0
    39.         .for (ebx = 1: ebx <= sqr_lim: ebx++); j:ebx
    40.             ;y2 += 2 * j - 1
    41.             lea     edi, [edi+ebx*2-1]
    42.             ;n = 4 * x2 + y2;
    43.             lea     ecx, [esi*4+edi]    ;n:ecx
    44.             .if (ecx <= limit)
    45.                 ;n / 12
    46.                 mov     eax, 0AAAAAAABh
    47.                 mul     ecx
    48.                 shr     edx, 3  ;edx = n % 12
    49.                 imul    eax, edx, 12
    50.                 sub     eax, ecx
    51.                 .if (eax == -1 || eax == -5)
    52.                     ;is_prime[n] = !is_prime[n]
    53.                     mov     eax, pIsPrime
    54.                     xor     [eax][ecx], 1
    55.                 .endif
    56.                 inc     CountDIV
    57.             .endif
    58.             ;//// n = 3 * x2 + y2;
    59.             sub     ecx, esi    ;n -= x2; ;// Оптимизация
    60.             .if (ecx <= limit)
    61.                 ;n / 12
    62.                 mov     eax, 0AAAAAAABh
    63.                 mul     ecx
    64.                 shr     edx, 3  ;edx = n % 12
    65.                 imul    eax, edx, 12
    66.                 sub     eax, ecx
    67.                 .if (eax == -7)
    68.                     ;is_prime[n] = !is_prime[n]
    69.                     mov     eax, pIsPrime
    70.                     xor     [eax][ecx], 1
    71.                 .endif
    72.                 inc     CountDIV
    73.             .endif
    74.             ;//// n = 3 * x2 - y2;
    75.             ;n -= 2 * y2; ;// Оптимизация
    76.             .if (i > ebx)
    77.                 sub     ecx, edi
    78.                 sub     ecx, edi
    79.                 .if (ecx <= limit)
    80.                     ;n % 12
    81.                     mov     eax, 0AAAAAAABh
    82.                     mul     ecx
    83.                     shr     edx, 3
    84.                     imul    eax, edx, 12
    85.                     sub     eax, ecx
    86.                     .if (eax == -11)
    87.                         ;is_prime[n] = !is_prime[n]
    88.                         mov     eax, pIsPrime
    89.                         xor     [eax][ecx], 1
    90.                     .endif
    91.                     inc     CountDIV
    92.                 .endif
    93.             .endif
    94.         .endfor
    95.     .endfor
    96.     ;// Отсеиваем кратные квадратам простых чисел в интервале [5, sqrt(limit)].
    97.     ;// (основной этап не может их отсеять)
    98.     ASSUME  esi:ptr byte, eax:nothing
    99.     mov     esi, pIsPrime
    100.     .for (edi = 5: edi <= sqr_lim: edi++)
    101.         .if ([esi][edi])
    102.             ;n = i * i  //n:eax
    103.             mov     eax, edi
    104.             mul     edi
    105.             .for (ecx = eax: ecx <= limit: ecx += eax); j:ecx
    106.                 mov     [esi][ecx], false
    107.             .endfor
    108.         .endif
    109.     .endfor
    110.     ;// Посчёт простых чисел
    111.     mov     ebx, 3
    112.     .for (edi=6, edx=0, ecx=1: edi <= limit: edi++)  ;// добавлена проверка делимости на 3 и 5. В оригинальной версии алгоритма потребности в ней нет.
    113.         .if ([esi][edi] && edx && ecx)
    114.             inc     ebx
    115.         .endif
    116.         inc     edx
    117.         .if (edx==3)
    118.             xor     edx, edx
    119.         .endif
    120.         inc     ecx
    121.         .if (ecx==5)
    122.             xor     ecx, ecx
    123.         .endif
    124.     .endfor
    125.     GlobalFree(esi)
    126.     ASSUME  esi:nothing
    127.     mov     eax, ebx
    128.     ret
    129. CountPrimes endp
    130. align_proc
    131. main proc C argc:sdword, argv:ptr ptr, envp:ptr
    132. local tm:dword, a:dword, b:dword
    133.     .if (argc>=2)
    134.         mov     ebx, argv
    135.         .if (argc>=3)
    136.             mov     a, atoi([ebx+1*4])
    137.             mov     b, atoi([ebx+2*4])
    138.         .else
    139.             mov     a, 2
    140.             mov     b, atoi([ebx+1*4])
    141.         .endif
    142.     .else
    143.         printf("used: Primes from to  OR  Primes to\n")
    144.     .endif
    145.     mov     tm, clock()
    146.     mov     ebx, CountPrimes(b) ;numPrimes=
    147.     clock()
    148.     sub     eax, tm
    149.     printf("Primes[%u, %u] = %u  time = %d ms\n", a, b, ebx, eax)
    150.     printf("CountDIV = %u\n", CountDIV)
    151.     xor     eax, eax
    152.     ret
    153. main endp
    154. main_startup3_END
    155.  
    Ввод 1000000000(млрд), результат: 52769865 время 12779 мс, деление 1054869776
    Процессор райзен 3600Х, Хеон 5450 завтра если время будет. Если деление не оптимизировать, то намного медленней.
     
  13. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    563
    Хеон 1 млрд выполнил за 32737 мс. Тут код сложней, оптимизирован, и райзен убедительно выигрывает.
     
    UbIvItS нравится это.
  14. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    563
    Занятно, но 32 битная версия дала неправильный результат при 1 млрд.
    Код (ASM):
    1.  
    2. ;; простые числа v0.06
    3. .x64
    4. ;.model flat, stdcall
    5. option casemap:none
    6. option  frame:auto
    7. option  LITERALS:ON
    8. IF @Platform EQ 1
    9.     APP_WIN64       EQU 1
    10. ENDIF
    11. include types.inc
    12. include windows.inc
    13. include kernel32.inc
    14. include msvcrt.inc
    15. includelib kernel32.lib
    16. includelib msvcrt.lib
    17. include \assemblers\include\macros.asm
    18. .data?
    19. CountDIV        qword ?
    20. .code
    21. align_proc
    22. CountPrimes proc (qword) uses rsi rdi rbx limit:qword
    23. local sqr_lim:qword
    24.     mov     limit, rcx
    25.     ;// Инициализация решета
    26. ;   sqr_lim = (int)sqrt((long double)limit);
    27.     fild    limit
    28.     fsqrt
    29.     fistp   sqr_lim
    30.     mov     rsi, GlobalAlloc(GPTR, limit)   ;pIsPrime:HGLOBAL
    31.     ASSUME  rsi:ptr byte
    32.     mov     [rsi][2], true
    33.     mov     [rsi][3], true
    34.     ;// Предположительно простые — это целые с нечётным числом
    35.     ;// представлений в данных квадратных формах.
    36.     ;// x2 и y2 — это квадраты i и j (оптимизация).
    37.     mov     r10, 0AAAAAAAAAAAAAAABh
    38.     xor     r11, r11
    39.     xor     r8, r8  ;x2:r8 = 0
    40.     .for (r9 = 1: r9<=sqr_lim: r9++);i:r9
    41.         ;x2 += 2 * r9 - 1
    42.         lea     r8, [r8+r9*2-1]
    43.         xor     rdi, rdi    ;y2:rdi = 0
    44.         .for (rbx = 1: rbx <= sqr_lim: rbx++); j:rbx
    45.             ;y2 += 2 * j - 1
    46.             lea     rdi, [rdi+rbx*2-1]
    47.             ;n = 4 * x2 + y2;
    48.             lea     rcx, [r8*4+rdi] ;n:rcx
    49.             .if (rcx <= limit)
    50.                 ;n / 12
    51.                 mov     rax, r10
    52.                 mul     rcx
    53.                 shr     rdx, 3  ;rdx = n / 12
    54.                 neg     rdx
    55.                 lea     rdx, [rdx+rdx*2]
    56.                 lea     rax, [rcx+rdx*4]
    57.         ;       imul    rax, rdx, 12
    58.         ;       sub     rax, rcx
    59.                 .if (rax == 1 || rax == 5)
    60.                     ;is_prime[n] = !is_prime[n]
    61.                     xor     [rsi][rcx], 1
    62.                 .endif
    63.                 inc     CountDIV
    64.             .endif
    65.             ;//// n = 3 * x2 + y2;
    66.             sub     rcx, r8 ;n -= x2; ;// Оптимизация
    67.             .if (rcx <= limit)
    68.                 ;n / 12
    69.                 mov     rax, r10
    70.                 mul     rcx
    71.                 shr     rdx, 3  ;rdx = n % 12
    72.                 neg     rdx
    73.                 lea     rdx, [rdx+rdx*2]
    74.                 lea     rax, [rcx+rdx*4]
    75.         ;       imul    rax, rdx, 12
    76.         ;       sub     rax, rcx
    77.                 .if (rax == 7)
    78.                     ;is_prime[n] = !is_prime[n]
    79.                     xor     [rsi][rcx], 1
    80.                 .endif
    81.                 inc     CountDIV
    82.             .endif
    83.             ;//// n = 3 * x2 - y2;
    84.             .if (r9 > rbx)
    85.                 ;n -= 2 * y2; ;// Оптимизация
    86.                 sub     rcx, rdi
    87.                 sub     rcx, rdi
    88.                 .if (rcx <= limit)
    89.                     ;n % 12
    90.                     mov     rax, r10
    91.                     mul     rcx
    92.                     shr     rdx, 3  ;rdx = n % 12
    93.                     neg     rdx
    94.                     lea     rdx, [rdx+rdx*2]
    95.                     lea     rax, [rcx+rdx*4]
    96.         ;           imul    rax, rdx, 12
    97.         ;           sub     rax, rcx
    98.                     .if (rax == 11)
    99.                         ;is_prime[n] = !is_prime[n]
    100.                         xor     [rsi][rcx], 1
    101.                     .endif
    102.                     inc     CountDIV
    103.                 .endif
    104.             .endif
    105.         .endfor
    106.     .endfor
    107.     ;// Отсеиваем кратные квадратам простых чисел в интервале [5, sqrt(limit)].
    108.     ;// (основной этап не может их отсеять)
    109.     .for (rdi = 5: rdi <= sqr_lim: rdi++)
    110.         .if ([rsi][rdi])
    111.             ;n = i * i  //n:rax
    112.             mov     rax, rdi
    113.             mul     rdi
    114.             .for (rcx = rax: rcx <= limit: rcx += rax); j:rcx
    115.                 mov     [rsi][rcx], false
    116.             .endfor
    117.         .endif
    118.     .endfor
    119.     ;// Подсчёт простых чисел
    120.     mov     rbx, 3
    121.     .for (rdi=6, rdx=0, rcx=1: rdi <= limit: rdi++)  ;// добавлена проверка делимости на 3 и 5. В оригинальной версии алгоритма потребности в ней нет.
    122.         .if ([rsi][rdi] && rdx && rcx)
    123.             inc     rbx
    124.         .endif
    125.         inc     rdx
    126.         .if (rdx>=3)
    127.             sub     rdx, 3
    128.         .endif
    129.         inc     rcx
    130.         .if (rcx>=5)
    131.             sub     rcx, 5
    132.         .endif
    133.     .endfor
    134.     GlobalFree(rsi)
    135.     ASSUME  rsi:nothing
    136.     mov     rax, rbx
    137.     ret
    138. CountPrimes endp
    139. align_proc
    140. main proc frame argc:sdword, argv:ptr ptr, envp:ptr
    141. local tm:sdword, a:qword, b:qword
    142.     mov     argc, ecx
    143.     mov     argv, rdx
    144.     mov     envp, r8
    145.     .if (argc>=2)
    146.         mov     rbx, argv
    147.         .if (argc>=3)
    148.             mov     a, atoi([rbx+1*8])
    149.             mov     b, atoi([rbx+2*8])
    150.         .else
    151.             mov     a, 2
    152.             mov     b, atoi([rbx+1*8])
    153.         .endif
    154.         mov     tm, clock()
    155.         mov     rbx, CountPrimes(b) ;numPrimes=
    156.         clock()
    157.         sub     eax, tm
    158.         printf$("Primes[%u, %u] = %u  time = %d ms\n", a, b, rbx, eax)
    159.         printf$("CountDIV = %u\n", CountDIV)
    160.     .else
    161.         printf$("used: Primes from to  OR  Primes to\n")
    162.     .endif
    163.     xor     eax, eax
    164.     ret
    165. main endp
    166. main_startup3_END
    Переполнение произошло в строчке n = 4 * x2 + y2;
    64 битная версия дала 50847534, подсчитала чуть быстрей 12274 мс.
    А теперь версия на С++
    Код (C++):
    1.  
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #include <math.h>
    5. #include <time.h>
    6. size_t  CountDIV = 0;
    7. size_t  CountPrimes(size_t limit)
    8. {
    9.     size_t  sqr_lim = (size_t)sqrt((double)limit);
    10.     bool    *pIsPrime = new bool[limit+1];
    11.     pIsPrime[2] = true;
    12.     pIsPrime[3] = true;
    13.     // Предположительно простые — это целые с нечётным числом
    14.     // представлений в данных квадратных формах.
    15.     // x2 и y2 — это квадраты i и j (оптимизация).
    16.     for (size_t i = 1, x2 = 0; i <= sqr_lim; ++i) {
    17.         x2 += 2 * i - 1;
    18.         for (size_t j = 1, y2 = 0; j <= sqr_lim; ++j) {
    19.             y2 += 2 * j - 1;
    20.             size_t  n = 4 * x2 + y2;
    21.             if (n<=limit && (n%12 == 1 || n%12 == 5))
    22.                 pIsPrime[n] = !pIsPrime[n];
    23.             // n = 3 * x2 + y2;
    24.             n -= x2; // Оптимизация
    25.             if (n<=limit && n%12 == 7)
    26.                 pIsPrime[n] = !pIsPrime[n];
    27.             // n = 3 * x2 - y2;
    28.             n -= 2 * y2; // Оптимизация
    29.             if (i>j && n<=limit && n%12 == 11)
    30.                 pIsPrime[n] = !pIsPrime[n];
    31.         }
    32.     }
    33.     // Отсеиваем кратные квадратам простых чисел в интервале [5, sqrt(limit)].
    34.     // (основной этап не может их отсеять)
    35.     for (size_t i = 5; i <= sqr_lim; ++i) {
    36.         if (pIsPrime[i]) {
    37.             size_t  n = i * i;
    38.             for (size_t j = n; j <= limit; j += n)
    39.                 pIsPrime[j] = false;
    40.         }
    41.     }
    42.     // Посчёт простых чисел
    43.     size_t  count = 3;
    44.     for (size_t i = 6; i <= limit; ++i) {  // добавлена проверка делимости на 3 и 5. В оригинальной версии алгоритма потребности в ней нет.
    45.         if (pIsPrime[i] && i%3!=0 && i%5!=0)
    46.             count++;
    47.     }
    48.     delete[] pIsPrime;
    49.     return count;
    50. }
    51. int main(int argc, const char **argv, const char **envp)
    52. {
    53.     if ( argc < 2 ){
    54.         printf("used: Primes from to  OR  Primes to\n");
    55.     } else {
    56.         size_t  a,b,numPrimes;
    57.         if (argc < 3){
    58.             a = 2;
    59.             b = atoi(argv[1]);
    60.         } else {
    61.             a = atoi(argv[1]);
    62.             b = atoi(argv[2]);
    63.         }
    64.         clock_t tm = clock();
    65.         numPrimes = CountPrimes(b);
    66.         tm = clock() - tm;
    67.         printf("Primes[%u, %u] = %u  time = %d ms\n", a, b, numPrimes, tm);
    68.         printf("CountDIV = %u\n", CountDIV);
    69.     }
    70.     return 0;
    71. }
    Тут точность зависит от платформы, желательно 64 битная. И код С++ чуть быстрей ассемблера 32, и чуть медленней 64.
    Вообще, смысл топика как раз тесты: Ассемблер, С/С++, Питон. С питоном-питухоном у меня очень плохо, так что кто бы портировал код С++ на питухон?
     
    UbIvItS нравится это.
  15. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.125
    Intro, ну-вот и Молодец + решето-то можно раскидывать на потоки :wink3:
    смысла нет - питоха для обёрток - на нём удобно собирать команду и отправлять на внешний модуль. :)
     
  16. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    563
    Athlon II x4 640 3ГГц время 34429 мс, чуть медленней Хеона, думаю тут и отсутствие кеша сказалось. Вероятно Феном на 3ГГц будет чуть быстрей.
     
  17. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    563
    Вот сделал оптимизацию, во первых делимости на 3 и 5 не нужна. И второе, булевы упакованные, вроде vector<bool> в плюсах тоже упакованный, но я по простому, по самодельному сделал.
    Код (C++):
    1. //Простые числа. v0.8
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #include <math.h>
    5. #include <time.h>
    6. #include <stdint.h>
    7. size_t  CountDIV = 0;
    8. size_t  CountPrimes(size_t limit)
    9. {
    10.     size_t  sqr_lim = (size_t)sqrt((double)limit);
    11.     uint8_t *pIsPrime = new uint8_t[limit/8+1];
    12.     pIsPrime[2/8] |= 1 << 2%8;
    13.     pIsPrime[3/8] |= 1 << 3%8;
    14.     // Предположительно простые — это целые с нечётным числом
    15.     // представлений в данных квадратных формах.
    16.     // x2 и y2 — это квадраты i и j (оптимизация).
    17.     for (size_t i = 1, x2 = 0; i <= sqr_lim; ++i){
    18.         x2 += 2 * i - 1;
    19.         for (size_t j = 1, y2 = 0; j <= sqr_lim; ++j){
    20.             y2 += 2 * j - 1;
    21.             size_t  n = 4 * x2 + y2;
    22.             if (n<=limit){
    23.                 if (n%12 == 1 || n%12 == 5)
    24.                     pIsPrime[n/8] ^= 1 << n%8;
    25.                 CountDIV++;
    26.             }
    27.             n -= x2;    // n = 3 * x2 + y2; //Оптимизация
    28.             if (n<=limit){
    29.                 if (n%12 == 7)
    30.                     pIsPrime[n/8] ^= 1 << n%8;
    31.                 CountDIV++;
    32.             }
    33.             n -= 2*y2;  // n = 3 * x2 - y2;// Оптимизация
    34.             if (i>j && n<=limit){
    35.                 if (n%12 == 11)
    36.                     pIsPrime[n/8] ^= 1 << n%8;
    37.                 CountDIV++;
    38.             }
    39.         }
    40.     }
    41.     // Отсеиваем кратные квадратам простых чисел в интервале [5, sqrt(limit)].
    42.     // (основной этап не может их отсеять)
    43.     for (size_t i = 5; i <= sqr_lim; ++i){
    44.         if (pIsPrime[i/8] & 1<<i%8){
    45.             for (size_t n = i*i, j = n; j <= limit; j += n)
    46.                 pIsPrime[j/8] &= ~(1<<j%8);
    47.         }
    48.     }
    49.     // Подсчёт простых чисел
    50.     size_t  count = 2;
    51.     for (size_t i = 5; i <= limit; i+=2)
    52.         count += (pIsPrime[i/8] & 1<<i%8) ? 1 : 0;
    53.    
    54.     delete[] pIsPrime;
    55.     return count;
    56. }
    57. int main(int argc, const char **argv, const char **envp)
    58. {
    59.     if ( argc < 2 ){
    60.         printf("used: Primes from to  OR  Primes to\n");
    61.     } else {
    62.         size_t  a,b,numPrimes;
    63.         if (argc < 3){
    64.             a = 2;
    65.             b = atoi(argv[1]);
    66.         } else {
    67.             a = atoi(argv[1]);
    68.             b = atoi(argv[2]);
    69.         }
    70.         clock_t tm = clock();
    71.         numPrimes = CountPrimes(b);
    72.         tm = clock() - tm;
    73.         printf("Primes[%u, %u] = %u  time = %d ms\n", a, b, numPrimes, tm);
    74.         printf("CountDIV = %u\n", CountDIV);
    75.     }
    76.     return 0;
    77. }
    В общем, вычислений стало больше, но программа стала быстрей из-за меньшего использования памяти. На райзене 9326 вместо 11040 мс. Надо студию поновей установить, а то старая только в Win32 работает.
    --- Сообщение объединено, 2 сен 2023 ---
    Вот немного от рефакторил, просто для наглядности использовал макрофункции, код тот же самый, но с макрофункциями наглядней и меньше шансов накосячить из-за опечаток.
    Код (C++):
    1. //Простые числа. v0.81
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #include <math.h>
    5. #include <time.h>
    6. #include <stdint.h>
    7. #define NewBools(name,N)        ( (name) = new uint8_t[(N)/8+1] )
    8. #define DelBools(name)          ( delete[] (name) )
    9. #define GetBool(name,N)         ( (name)[(N)/8] & 1<<(N)%8 )
    10. #define SetBoolTrue(name,N)     ( (name)[(N)/8] |= 1<<(N)%8 )
    11. #define SetBoolFalse(name,N)    ( (name)[(N)/8] &= ~(1<<(N)%8) )
    12. #define SetBoolNOT(name,N)      ( (name)[(N)/8] ^= 1<<(N)%8 )
    13. size_t  CountDIV = 0;
    14. size_t  CountPrimes(size_t limit)
    15. {
    16.     uint8_t *pIsPrime;
    17.     size_t  sqr_lim = (size_t)sqrt((double)limit);
    18.     NewBools(pIsPrime, limit);
    19.     SetBoolTrue(pIsPrime, 2);
    20.     SetBoolTrue(pIsPrime, 3);
    21.     // Предположительно простые — это целые с нечётным числом
    22.     // представлений в данных квадратных формах.
    23.     // x2 и y2 — это квадраты i и j (оптимизация).
    24.     for (size_t i = 1, x2 = 0; i <= sqr_lim; ++i){
    25.         x2 += 2 * i - 1;
    26.         for (size_t j = 1, y2 = 0; j <= sqr_lim; ++j){
    27.             y2 += 2 * j - 1;
    28.             size_t  n = 4 * x2 + y2;
    29.             if (n<=limit){
    30.                 if (n%12 == 1 || n%12 == 5)
    31.                     SetBoolNOT(pIsPrime, n);
    32.                 CountDIV++;
    33.             }
    34.             n -= x2;    // n = 3 * x2 + y2; //Оптимизация
    35.             if (n<=limit){
    36.                 if (n%12 == 7)
    37.                     SetBoolNOT(pIsPrime, n);
    38.                 CountDIV++;
    39.             }
    40.             n -= 2*y2;  // n = 3 * x2 - y2;// Оптимизация
    41.             if (i>j && n<=limit){
    42.                 if (n%12 == 11)
    43.                     SetBoolNOT(pIsPrime, n);
    44.                 CountDIV++;
    45.             }
    46.         }
    47.     }
    48.     // Отсеиваем кратные квадратам простых чисел в интервале [5, sqrt(limit)].
    49.     // (основной этап не может их отсеять)
    50.     for (size_t i = 5; i <= sqr_lim; ++i){
    51.         if (GetBool(pIsPrime, i)){
    52.             for (size_t n = i*i, j = n; j <= limit; j += n)
    53.                 SetBoolFalse(pIsPrime, j);
    54.         }
    55.     }
    56.     // Подсчёт простых чисел
    57.     size_t  count = 2;
    58.     for (size_t i = 5; i <= limit; i+=2)
    59.         count += GetBool(pIsPrime, i) ? 1 : 0;
    60.    
    61.     DelBools(pIsPrime);
    62.     return count;
    63. }
    64. int main(int argc, const char **argv, const char **envp)
    65. {
    66.     if ( argc < 2 ){
    67.         printf("used: Primes from to  OR  Primes to\n");
    68.     } else {
    69.         size_t  a,b,numPrimes;
    70.         if (argc < 3){
    71.             a = 2;
    72.             b = atoi(argv[1]);
    73.         } else {
    74.             a = atoi(argv[1]);
    75.             b = atoi(argv[2]);
    76.         }
    77.         clock_t tm = clock();
    78.         numPrimes = CountPrimes(b);
    79.         tm = clock() - tm;
    80.         printf("Primes[%u, %u] = %u  time = %d ms\n", a, b, numPrimes, tm);
    81.         printf("CountDIV = %u\n", CountDIV);
    82.     }
    83.     return 0;
    84. }
    --- Сообщение объединено, 2 сен 2023 ---
    И ещё дополнительные тесты. Закрыл все браузеры, и получил 8995 мс это этот код, и ассемблерный вариант х86 9258 мс и х64 8960 мс. Как видно свободный кеш заметно влияет.
    И я забыл самое главное.

    В общем, тут к неправильным тестам, тест ютуба не корректный показал что питон медленней С/Ассемблере всего в 10 раз. Но если взять код посложней разница будет более значительная думаю раз в 100. Да, питухон это сложный ЯП для сложных типов данных типа там нейросети, или ещё что-то аналогично по сложности. А для простых типов данных его использовать не очень выгодно, во только пограммисты питухунисты про это конечно не знаю, или знать не хотят.