Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет yigal_s ([info]yigal_s)
@ 2010-11-07 20:53:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
поэкспериментировал немного с interlock-операциями и получил очень странный результат.

Тестировал, в частности, функцию увеличения на единицу, написаную посредством InterlockedCompareExchange aka CAS. Интересовало меня, сколько раз этот самый CAS "сорвется" т.е. алгоритм уйдет на вторую попытку из за конфликта с другим тредом, при максимальной загрузке компьютера.

Загрузил я этой функцией увеличения на единицу одной и той же переменной -
четыре ядра, что не очень серьезно для мультипроцессорного теста,
но и не так чтоб мало. Уж что было.

Так вот, даже на четырех ядрах я получил менее одного процента конфликтов, т.е.
более 99% операций CAS окончились успехом.

Я сразу же глазам своим не поверил, и ради проверки точности вычисления процентов,
решил посчитать, сколько же вообще операций CAS в процентах
я выполнил. Должен был получить что-то около 101% (дополнительный процент за счет конфликтов),
но получил что-то вроде 140%. При этом, и процент конфликтов подскочил до 40%.

На самом деле, вот эти 40% - это более менее логичный процент конфликтов, но
каким образом я смог его получить только лишь введя в цикл инкремент дополнительной переменной -
общего числа вызовов, я так понять и не смог. Кстати, если попеременно инкрементировать в цикле с помощью CAS две разных переменных, уже не подсчитывая общее число вызовов, то опять же,
число конфликтов где-то около тех же 40%.

А вот как четыре ядра могут сделать менее 1% конфликтов, инкрементируя одну и ту же переменную -
совершенно непонятно.

UPD: снял точные замеры. Там не 1%, а 0.07%, семь сотых процентов конфликтов!
При поочередном же доступе через CAS к двум переменным, процент конфликтов уже 51%.


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


[info]kot_begemot@lj
2010-11-07 23:06 (ссылка)
Ну так для того чтобы интерлоком пользоваться, мало CAS использовать - ещё и membar нужен обязательно, иначе каждое ядро из своего кэша возьмёт своё значение той же самой переменной.
Оттуда и 99%, надо полагать.

(Ответить) (Ветвь дискуссии)


[info]yigal_s@lj
2010-11-07 23:13 (ссылка)
хмм... я вообще-то пользовался gcc-шными расширенями под x86. По-идее, там должен стоять lock префикс, который обеспечивает и membar.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]kot_begemot@lj
2010-11-08 02:10 (ссылка)
Я бы для верности сделал objdump -d - чтобы точно знать, что они там вызывают.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]yigal_s@lj
2010-11-08 02:34 (ссылка)
я сделаю.

но... если там не будет префикса lock, это будет международный скандал. :-)

Да и вообще, кэш у intel когерентный, так что модификация линий в одном кеше должна приводить к инвалидизации линий в другом кеше.

(Ответить) (Уровень выше)


[info]yigal_s@lj
2010-11-08 13:00 (ссылка)
нормально они все вызывают, с префиксом

(Ответить) (Уровень выше)


[info]yigal_s@lj
2010-11-08 13:04 (ссылка)
на данный момент, выяснилось, что конфликты появлялись в первую очередь из-за того, что две переменные, которые я инкрементировал, находились в одном кеш-лайне. Логики тут особой нет - как раз инкрементируя одну переменную, которая как бы находится в одном кеш лайне, число конфликтов - сотые процента. С двумя, видимо, "сбоит" что-то в кеш-протоколе.

После того, как я из разнёс в разные кеш-лайны, я получил опять же безумные 0.02% конфликтов на 2-х ядрах, и всё-таки реалистичные 10% конфликтов на 4-х ядрах.

Каким образом на 2-х ядрах получается 0.02%, мне по прежднему непонятно никак.

(Ответить)