Шедевр! Я даже под стол валиться не буду, так в подвал загляну.Leency wrote:как узнать размер стека я не знаю, но он ведь всегда равен 100, или нет?
Flood-it!
Ну размера стека будет таким, какой тебе нужен А то, что ничего не изменилось, это только на первый взгляд. Ведь по идее в случае CreateThread(#help,#stak) обращение к стеку будет портить данные, которые находятся перед stak, а сам stak вообще никак не будет использоваться. В данном случае перед stak расположен буфер proc_info Form, старшие (1024-72) байт которого никак не используются, поэтому никаких ошибок не возникает. Но ничто не мешает компилятору расместить неиницализированный stak в каком-нибудь другом месте (например, в конце исполнимого кода программы), тогда оба потока могут дать дуба.Leency wrote: а) как узнать размер стека я не знаю, но он ведь всегда равен 100, или нет? Заменил CreateThread(#help,#stak); на CreateThread(#help,#stak+100); ничего не изменилось. Всё работает и я решил оставить как было раньше. Тут пусть lev разбирается, он круче))
Про то что указатель надо ставить в конец области, а не в начало, я уже в чате писал - но зачем обращать внимание на комментарии какого-то хуя с горы. "Нам" ЯВУшникам море по колено.
Это есть плохо. КодIgorA wrote:Code: Select all
rand_x dd 0 align 4 rand_next: ;x(k+1) = (a*x(k)+c) mod m ; a=22695477, c=1, m=2^32 push eax mov eax,dword[rand_x] imul eax,22695477 inc eax mov dword[rand_x],eax pop eax ret
Code: Select all
push eax
mov eax,dword[rand_x]
imul eax,22695477
add eax,1
mov dword[rand_x],eax
pop eax
В смысле, проинлайнить вызов крохотной функции? Естественно, это ускорит жизнь, но раздует код. Или заменить inc на add? На фоне imul это не может дать 50% выигрыша. Если последнее, то наверняка дело в том, что из-за изменения размера плывут все дальнейшие адреса, и какие-то переменные или функции - align 4 для функции недостаточно - становятся выровненными.
Сделаем мир лучше!
inc и dec модифицируют только часть флагов, что создаёт зависимость от всех предыдущих записей в регистр флагов. Поэтому Интел рекомендовала заменять их add и sub.
The INC and DEC instructions modify only a subset of the bits in the flag register. This creates a dependence on all previous writes of the flag register. This is especially problematic when these instructions are on the critical path because they are used to change an address for a load on which many other instructions depend.
Только совсем гремучие чайники могут путаться с флагами inc/decSerge wrote:inc и dec модифицируют только часть флагов, что создаёт зависимость от всех предыдущих записей в регистр флагов. Поэтому Интел рекомендовала заменять их add и sub.The INC and DEC instructions modify only a subset of the bits in the flag register. This creates a dependence on all previous writes of the flag register. This is especially problematic when these instructions are on the critical path because they are used to change an address for a load on which many other instructions depend.
Ну еще наверное разработчики х86 из Интела
А вообще (с железячной точки зрения) inc/dec не только короче, но еще и экологичнее чем add/sub. Потому что при прочих равных условиях меньше вентилей требуется переключать в ALU и в конвейере -- экономьте электроэнергию!
Евангелие от Иоанна: стих 1[/size]
Code: Select all
; В начале было Слово:
B32: mov ax, os_stack ; Selector for os
Ох, ты права. Дело в выравнивании. Поправил align, скорость из-за этого падала.CleverMouse wrote:В смысле, проинлайнить вызов крохотной функции? Естественно, это ускорит жизнь, но раздует код. Или заменить inc на add? На фоне imul это не может дать 50% выигрыша. Если последнее, то наверняка дело в том, что из-за изменения размера плывут все дальнейшие адреса, и какие-то переменные или функции - align 4 для функции недостаточно - становятся выровненными.
Вообще-то я встречал упоминание, что на части процессоров add быстрее чем inc. В компиляторах также почему-то часто встречается замена sub на add, если работа идет с одним из постоянных значений. Например, когда в стеке под хранение локальных переменных место выделяется.
на суперскалярных процах add может распараллеливаться с некоторыми другими командами, но не со всеми. И в любом случае инкремент счетчика цикла требует ровно 1 такт, что с inc, что с add.
Но все это распараллеливание загибается раком, если ломается кэш. А кэш имеет обыкновение ломаться даже в Колибри. Потому что WinMap сильно раздутый.
Когда весь цикл умещается на одну кэш-страницу - тогда он будет крутиться с максимально возможной скоростью, причем вероятность этого при inc/dec существенно выше, чем с add/sub.
Но все это распараллеливание загибается раком, если ломается кэш. А кэш имеет обыкновение ломаться даже в Колибри. Потому что WinMap сильно раздутый.
Когда весь цикл умещается на одну кэш-страницу - тогда он будет крутиться с максимально возможной скоростью, причем вероятность этого при inc/dec существенно выше, чем с add/sub.
Потому и очень быстрая, что очень маленькая.diamond wrote:Колибри - не только очень быстрая, но еще и очень маленькая ОС
Оптимизация по размеру не всегда даёт выигрыш в скорости. Для P4 с его мизерным кешем это может быть критично, а декодер Атлонов например очень любит выравнивание кода на 4 байта в циклах и ветвлениях. Ещё AMD до вторых Феномов не умела рассчитывать esp в цепочках push/pop и
sub esp, ...
mov [esp],
mov [esp+4]
mov [esp+8] работало быстрее нескольких push.
А Интел не любили команду loop. У каждой микроархитектуры свои заморочки.
art_zh
Чайники или нет, но ложные взаимозависимости создают серьёзные проблемы для суперскалярных архитектур. Не случайно Интел и АМД рекомендуют использовать обнуляющие xor reg, reg или sub reg, reg для сброса ложных зависимостей между отдельными частями кода.
sub esp, ...
mov [esp],
mov [esp+4]
mov [esp+8] работало быстрее нескольких push.
А Интел не любили команду loop. У каждой микроархитектуры свои заморочки.
art_zh
Чайники или нет, но ложные взаимозависимости создают серьёзные проблемы для суперскалярных архитектур. Не случайно Интел и АМД рекомендуют использовать обнуляющие xor reg, reg или sub reg, reg для сброса ложных зависимостей между отдельными частями кода.
И я про то же. Как можно вручную оптимизировать код и сравнивать время выполнения команд, если их суперскалярный микрокод на каждой кривой козе реализован по-своему?Serge wrote:У каждой микроархитектуры свои заморочки.
Зато я точно знаю, что dec eax всегда в 5 раз короче, чем sub eax, 1 (про энергопотребление пока замнем для ясности). Поэтому даже если я поставлю выравнивание кода на 4 байта - то всегда выиграю и в размере, и в эффективности кэширования.
Правда, в некоторых (редких!) случаях возможен проигрыш в скорости - не более чем на 1 такт и то при очень удачном распараллеливании регистровых команд. Но что такое 1 такт по сравнению с десятками холостых тактов при промахе кэша?
Выравнивание адресов - да, нужно. Невыравненный адрес - это 1-2 лишних процессорных тактов в кэше, или несколько "длинных" шинных тактов при промахе.
в 5? Иногда в 3, емнип.
Code: Select all
83 c0 01 add $0x1,%eax
83 c3 01 add $0x1,%ebx
Да, твоя правда -
весит только 3 байта.
Так что поправлюсь: inc дает выигрыш при 4-байтовом выравнивании не каждый раз, а только в 50% случаев.
А вероятность вылета с отдельной кэшируемой страницы при этом уменьшается не на 6%, а только на 3%
Code: Select all
add eax, byte 1
весит только 3 байта.
Так что поправлюсь: inc дает выигрыш при 4-байтовом выравнивании не каждый раз, а только в 50% случаев.
А вероятность вылета с отдельной кэшируемой страницы при этом уменьшается не на 6%, а только на 3%
Небольшой недочёт. Для начала новой игры нужно жать кнопку, вопрос - зачем? Отрисовали win, подождали 2 сек и вывели новое поле.
Who is online
Users browsing this forum: No registered users and 1 guest