Pull to refresh

Comments 9

А где в опросе опция "(сломан) проброс (железного) таймера в виртуалку"? Помнится, в ранних VirtualBox нечто такое было.

А он не сломан (мы это выяснили еще в первой части, ну и здесь видно):
трейсинг показывает что clock_gettime(CLOCK_REALTIME) возвращает корректные значения

Но если хотите - добавлю.

А просто при делении 1642516506243048649 / 1e9 получается воспроизвести неправильный результат?

ps: там два действия int64->double и потом деление. Можете оба действия залогировать.
Дело в том что 1642516506243048649 не влазит в double и получиться 1642516506243048704.
Но глючит скорее всего деление, и оно может глючить не всегда, а из за соседних потоков или переключений контекстов. Но глюк точно не связан с памятью, т.к. значения еще не покидало кэш первого уровня.

pps: кстати асемблерный код зависит от платформы. может быть как sse(cvtsi2sd,divsd) так и avx(vcvtsi2sd,vdivsd). так что не помешает в тесте добавить опции компилятора gcc -O2 -mach=native

А просто при делении 1642516506243048649 / 1e9 получается воспроизвести неправильный результат?

Думаю что временами да, но... спросить чего и ждать потом 2-3 дня (а он как говорилось уже, нукуда не торопится), то такое.

там два действия int64->double и потом деление. Можете оба действия залогировать.

Можно, то оно можно, токма с хайзенбагами осторожно нужно - они чем больше их дебажишь или обвешиваешь логами, тем хуже воспроизводятся, плавали - знаем (приходилось по роду деятельности бороться).

Но глюк точно не связан с памятью, т.к. значения еще не покидало кэш первого уровня

Вот про кеш я бы не был так уверен, ибо 1) вымывается он всякой паразитной дрянью, да на виртуалке то, и 2) та же внезапная запись рядом в том же неудачно выравненном блоке памяти другим каким потоком может вызвать invalidate для всего куска что в L2, а затем и в L1 (я про согласованность кеша и когерентность памяти). Он у Ryzen9 3900X хоть и большой (если не ошибаюсь 64MB), но под виртуалку ему отдали всего 512K судя по инфо о системе:
Info: Single Core model: AMD Ryzen 9 3900X bits: 64 type: UP L2 cache: 512 KiB
опять же на single core model там контекст-свич контекст-свичем погоняет.

Вот только слишком уж "консистетные" результаты для битой памяти, при том если то память, то здесь действительно стэк (это не объекты питона из кучи). А битый стек должен бы худо бедно сегфолтить где-то еще, а этого нет и в помине судя по всему.

Дело в том что 1642516506243048649 не влазит в double и получиться 1642516506243048704.

Оно и понятно, только на нормально работаюшей системе это поменеят несколько десятков наносекунд (55 если быдь точным), но никак не секунды т.е. при делении на лярд как бы не очень важно в контексте статьи - время, округленное до миллисекунд, как было 1642516506.243 так и останется 1642516506.243.

Так ошибка может быть не при делении а при преобразовании.

Может, согласен... и что для cvtsi2sd, что для fild+fstp...
И возможно даже более вероятно чем при делении, потому как меня смущает, что для python 2.7 оно там совсем не воспроизводимо. А если я правильно вспоминаю исходники, то вот эта штука с "многоступенчатым" преобразованием вида timespec --> int64_t --> double как раз где-то в 3-й версии в этом виде появилась (3.6 до 3.8 если не ошибаюсь), т.е. каст из doubleword integer в scalar double может раньше и не был там, поэтому оно там и работает в python 2.7 худо бедно.

Другое дело что есть ли принципиальная разница? - ведь что там, что там FPU сломан (ну или что там еще барахлит), а конкретика в котором месте точно барахлит должна по хорошему лишь хостера интересовать, ну или AMD или возможно KVM, если то вдруг софтовые проблемы виртуализации.

Всё было бы проще если бы машинка была под рукой, а так... муторно оно.

Хотя всё равно странно - как такое не вылазит повсеместно, ибо что cvtsi2sd+divsd, что fild+fstp+fdiv настолько часто должны присутствовать, что оно бы всё равно где-нибудь да проявилось. Аннет, токма тут вылазит.

У меня он только два варианта генерит:
pxor      xmm0, xmm0                         ; xmm0=0
cvtsi2sd  xmm0, r8                           ; xmm0.d0=double(r8)
movsd     QWORD PTR 24[rsp], xmm0            ; d=xmm0.d0
movsd     xmm0, QWORD PTR 24[rsp]            ; xmm0.d0=d
divsd     xmm0, QWORD PTR .LC_1E9[rip]       ; xmm0.d0=xmm0.d0/1e9
movsd     QWORD PTR 24[rsp], xmm0            ; d=xmm0.d0
movsd     xmm0, QWORD PTR 24[rsp]            ; xmm0.d0=d
movsd     QWORD PTR 16[rsp], xmm0            ; ...

vxorpd    xmm3, xmm3, xmm3                   ; xmm3=0
vcvtsi2sd xmm0, xmm3, r8                     ; xmm0=double(0,r8)
vmovsd    QWORD PTR 24[rsp], xmm0            ; d=xmm0.d0
vmovsd    xmm0, QWORD PTR 24[rsp]            ; xmm0.d0=d
vdivsd    xmm0, xmm0, QWORD PTR .LC_1E9[rip] ; xmm0.d0=xmm0.d0/1e9
vmovsd    QWORD PTR 24[rsp], xmm0            ; d=xmm0.d0
vmovsd    xmm0, QWORD PTR 24[rsp]            ; xmm0.d0=d
vmovsd    QWORD PTR 16[rsp], xmm0            ; ...
И тут мест для проверки даже больше 2х
Sign up to leave a comment.

Articles