Каков механизм write barrier
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 06.05.04 15:29
Оценка: +2
По данной ссылке
http://www.rsdn.ru/Forum/Message.aspx?mid=558877&only=1
Автор: Yury_Malich
Дата: 03.03.04

есть обяснение почему при обмене ссылками на объекты происходит торможение раз в 10-12 по сравнению с обменами валуе типов.
В тестах http://www.rsdn.ru/Forum/Message.aspx?mid=558877#558877
Автор: Yury_Malich
Дата: 03.03.04

это очень хорошо видно

Интересен сам по себе механизм такого поведения
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re: Каков механизм write barrier
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.05.04 16:57
Оценка:
Здравствуйте, Serginio1, Вы писали:

Я вот тоже слышал этот термин несклько раз, но он как-то упоминается в сколь. Типа "обсуждение этой фичи выходит за рамки...".
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Каков механизм write barrier
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 06.05.04 17:19
Оценка: 26 (2)
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Serginio1, Вы писали:


VD>Я вот тоже слышал этот термин несклько раз, но он как-то упоминается в сколь. Типа "обсуждение этой фичи выходит за рамки...".

Во блин нашел аж за 1993 год
http://research.sun.com/research/self/papers/write-barrier.html
Каким то образом наверное write barier связан с GC но это возможно если учет ссылок GC был произведен, но обычно это происходит при выделении определенного количества памяти. С другой стороны на Array.Copy write-barrier практически не влияет (вернее есть небольшое замедление по сравнению с валуе типами, но не такое катострофическое, причем в видби это практически не заметно).
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re[2]: Каков механизм write barrier
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.05.04 10:22
Оценка: 15 (1)
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Serginio1, Вы писали:


VD>Я вот тоже слышал этот термин несклько раз, но он как-то упоминается в сколь. Типа "обсуждение этой фичи выходит за рамки...".


Интересно что, при инлайне тормозов нет (веренее есть но только в 2 раза по ставнению с int)


public class IntClass
    { 
      public int value;
          public IntClass(int val)
          {
              value = val;
          }
    }




    public static void Run8(System.Windows.Forms.TextBox _log, int Count)
        {
            _log.AppendText("Сортировка вставка IntClass массива Count=" + Count.ToString() + Environment.NewLine);

            Utils.PerfCounter timer = new PerfCounter();
            int r = 666;
            IntClass[] IntClassArray = new IntClass[Count];
            IntClass[] IntClassArray1 = new IntClass[Count];

            while (r < 666000)
            {
                IntRandim F = new IntRandim(r, 0, Count);

                timer.Start();
                for (int i = 0; i < Count; i++)
                {
                    IntClassArray1[i] = new IntClass(i);
                    
                }

                // перемешаем массив
                for (int i = 0; i < Count; i++)
                {
                    int temp = F.Next();
                    int temp2 = F.Next();
                    IntClass temp3 = IntClassArray1[temp];

                    IntClassArray1[temp] = IntClassArray1[temp2];
                    IntClassArray1[temp2] = temp3;
                }

                // сортировка вставками

                IntClassArray[0] = IntClassArray1[0];
                
                    for (int i = 1; i < Count; i++)
                    {
                        Int32 L = 0;
                        Int32 R = i-1;
                        IntClass Current=IntClassArray1[i];
                        int key = Current.value;
                        //int key = IntClassArray1[i].value;

                    while (L < R)
                        {
                            int Midl = (L + R) >>1;

                            if (IntClassArray[Midl].value <= key)
                                L = Midl + 1;
                            else
                                R = Midl;
                        }

                                                

                        for (int j = i; j > L; j--)
                            IntClassArray[j] = IntClassArray[j - 1];

                        IntClassArray[L] = IntClassArray1[i];
                    
                    }
                
                _log.AppendText(string.Format(" Время={0}" + Environment.NewLine, timer.Finish()));
                for (int i = 1; i < Count; i++)
                    if (IntClassArray[i].value != i)
                    {
                        _log.AppendText(string.Format(" i={0} <> {1}", i, IntClassArray[i].value));
                        return;
                    }

                r *= 10;
            }
        }



Но такой вариант безбожно тормозит пропорционально квадрату занимаемой памяти с применением Add3.

 public class Int32AsObjectInsertSort
    {
        public IntClass[] ar;
        public Int32 count;
        private Int32 temp;
        private Int32 Midl;
        public Int32AsObjectInsertSort(Int32 Size)
        {
            ar = new IntClass[Size];
            count = 0;
        }
        private Int32 ПоискПоловиннымДелением(Int32 key)
        {
            Int32 i = 0;
            Int32 j = count - 1;

            while (i <= j)
            {
                Midl = (i + j) >>1;
                if (ar[Midl].value > key) { j = Midl - 1; }
                else if (ar[Midl].value < key) { i = Midl + 1; }
                else { return i; }
            }

            return i;
        }

        public void Add3(IntClass value)
        {
            if (count == 0)
            {
                count = 1;
                ar[0] = value;
            }
            else
            {
                Int32 index = ПоискПоловиннымДелением(value.value);

                for (Int32 i = count; i > index; i--)
                {
                    ar[i] = ar[i - 1];
                }

                ar[index] = value;
                count++;
            }
        }
    }
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re: Каков механизм write barrier
От: mihailik Украина  
Дата: 13.05.04 16:36
Оценка: 19 (2)
Ещё немного из свежего блога:

volatile and MemoryBarrier() Brad Adams Blog
... << RSDN@Home 1.1.3 stable >>
Re[2]: Каков механизм write barrier
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.04 09:19
Оценка:
Здравствуйте, mihailik, Вы писали:

M>Ещё немного из свежего блога:


M>volatile and MemoryBarrier() Brad Adams Blog

Спасибо. Нужно будет попобовать.
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re[3]: Каков механизм write barrier
От: mihailik Украина  
Дата: 14.05.04 12:42
Оценка: +1
M>>volatile and MemoryBarrier() Brad Adams Blog
S> Спасибо. Нужно будет попобовать.

Я вот вчитался сегодня с утра. По-моему там какой-то немного другой барьер. Так ничего чётко Адамс не сакзал.

Вообще впервые узнал, что в C# есть слово "volatile".
... << RSDN@Home 1.1.3 stable >>
Re[4]: Каков механизм write barrier
От: Andre Украина  
Дата: 14.05.04 12:50
Оценка: 16 (1)
M>Я вот вчитался сегодня с утра. По-моему там какой-то немного другой барьер. Так ничего чётко Адамс не сакзал.

Nvf в комментариях куча ссылок на статьи различные проскакивала.

M>Вообще впервые узнал, что в C# есть слово "volatile".


... << RSDN@Home 1.1.3 beta 2 >> :: L Fudge — Love Letters Feat Jasmin
Я бы изменил мир — но Бог не даёт исходников...
Re[5]: Каков механизм write barrier
От: mihailik Украина  
Дата: 14.05.04 12:53
Оценка:
A>Nvf в комментариях куча ссылок на статьи различные проскакивала.

О, а я комментарии обычно не читаю. Значит нужно читать!
... << RSDN@Home 1.1.3 stable >>
Re[4]: Каков механизм write barrier
От: alexkro  
Дата: 15.05.04 09:15
Оценка: 27 (1)
Здравствуйте, mihailik, Вы писали:

M>>>volatile and MemoryBarrier() Brad Adams Blog

S>> Спасибо. Нужно будет попобовать.

M>Я вот вчитался сегодня с утра. По-моему там какой-то немного другой барьер. Так ничего чётко Адамс не сакзал.


Естественно другой. Это hardware write barrier. Нужен для того, чтобы кэшы синхронизировать и делать flush processor pipeline, например.

А в начале речь шла о barrier как о технике применяемой в generational GCs, которая помогает разделять generations.

M>Вообще впервые узнал, что в C# есть слово "volatile".


Есть. volatile в C# работает почти как в C++, только в добавление чтение volatile переменных имеет acquire semantics, а запись — release semantics. Очень полезно, когда процессор может производить изменение порядка чтения/записи в память (reads & writes reordering).

Пара ссылок по этой теме:
http://discuss.develop.com/archives/wa.exe?A2=ind0203B&amp;L=DOTNET&amp;P=R375
http://blogs.msdn.com/cbrumme/archive/2003/05/17/51445.aspx
Re[3]: Каков механизм write barrier
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 18.05.04 14:00
Оценка:
Здравствуйте, Serginio1, Вы писали:

Кстати дома то у меня видби и эти два варианта отрабатывают по разному, на работе провел тест с 1.1 картина и отрабатывают одинаково.
В видби они кое что подправили.
Интересно этот же тест прогнать на 2005.
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re[4]: Каков механизм write barrier
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.05.04 20:44
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S> Кстати дома то у меня видби и эти два варианта отрабатывают по разному, на работе провел тест с 1.1 картина и отрабатывают одинаково.

S> В видби они кое что подправили.
S> Интересно этот же тест прогнать на 2005.

А в чем разница?
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Каков механизм write barrier
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.05.04 09:56
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, Serginio1, Вы писали:


S>> Кстати дома то у меня видби и эти два варианта отрабатывают по разному, на работе провел тест с 1.1 картина и отрабатывают одинаково.

S>> В видби они кое что подправили.
S>> Интересно этот же тест прогнать на 2005.

VD>А в чем разница?

Разница в том, что в 1.1 эти два алгоритма отрабатывают одинаково, то есть сортировка в одной процедуре и сортировка через добавление (Int32AsObjectInsertSort.Add3)
и writw barier и в обоих случаях.
В видби сортировка в в процедуре в 2 раза медленне чем на интах , но стабильно, при сортировке Int32AsObjectInsertSort.Add3 write barier остается и геометрическая прогрессия замедления от размера данных как в 1.1
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re[3]: Каков механизм write barrier
От: kkav Россия  
Дата: 21.05.04 08:06
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, mihailik, Вы писали:


M>>Ещё немного из свежего блога:


M>>volatile and MemoryBarrier() Brad Adams Blog

S> Спасибо. Нужно будет попобовать.

По указанной ссылке написано:
 public static Singleton Value {
    get {
        if (Singleton.value == null) {
            lock (syncRoot) {
                if (Singleton.value == null) {
                    Singleton newVal = new Singleton();
                    // Insure all writes used to construct new value have been flushed. 
                    System.Threading.Thread.MemoryBarrier(); 
                    Singleton.value = newVal;         // publish the new value 
                }
            }
        }
        return Singleton.value;
    }
}


Почему System.Threading.Thread.MemoryBarrier();
Выполняется до Singleton.value = newVal;
а не после него, если мы боимся, что к моменту выполнения
другим потоком (lock (syncRoot) { if (Singleton.value == null) ...)
Singleton.value еще не будет еще присвоено?
Не логичнее ли высвободить кэш после присвоения?
... << RSDN@Home 1.1.3 beta 2 >>
Re[4]: Каков механизм write barrier
От: alexkro  
Дата: 21.05.04 09:26
Оценка:
Здравствуйте, kkav, Вы писали:

K>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, mihailik, Вы писали:


M>>>Ещё немного из свежего блога:


M>>>volatile and MemoryBarrier() Brad Adams Blog

S>> Спасибо. Нужно будет попобовать.

K>По указанной ссылке написано:

K>
K> public static Singleton Value {
K>    get {
K>        if (Singleton.value == null) {
K>            lock (syncRoot) {
K>                if (Singleton.value == null) {
K>                    Singleton newVal = new Singleton();
K>                    // Insure all writes used to construct new value have been flushed. 
K>                    System.Threading.Thread.MemoryBarrier(); 
K>                    Singleton.value = newVal;         // publish the new value 
K>                }
K>            }
K>        }
K>        return Singleton.value;
K>    }
K>}      
K>


Там в одном из комментариев более правильная версия есть с двумя memory barriers.

K>Почему System.Threading.Thread.MemoryBarrier();

K>Выполняется до Singleton.value = newVal;
K>а не после него, если мы боимся, что к моменту выполнения
K>другим потоком (lock (syncRoot) { if (Singleton.value == null) ...)
K>Singleton.value еще не будет еще присвоено?
K>Не логичнее ли высвободить кэш после присвоения?

Допустим, делается так как ты предлагаешь. Тогда есть следующий вариант развития событий: первый поток входит в lock выделяет Singleton и инициализирует Singleton.value, но замещается вторым потоком прям перед вызовом MemoryBarrier(). Второй поток проверяет Singleton.value, его значение уже не null, и оно тут-же возвращается из функции. Далее второй поток пытается использовать тот объект Singleton, который он получил, но так как сконструированный объект Singleton еще находится в кэше первого потока (пусть эти потоки выполняются на разных процессорах), то второй поток, думая, что он обращается к памяти Singleton'а, на самом деле читает память, в которой еще мусор. Вот так.

Вопрос этот вообщем очень интересный. Почитай пост Vance Morrison'а (ссылка в блоге Брада) про моделирование поведения памяти с помощью перестановок чтения/записи. А так же про модель памяти CLR в блоге Chris Brumme'а.
Re[5]: Каков механизм write barrier
От: Дарней Россия  
Дата: 31.05.04 04:09
Оценка:
Здравствуйте, alexkro, Вы писали:

A>Допустим, делается так как ты предлагаешь. Тогда есть следующий вариант развития событий: первый поток входит в lock выделяет Singleton и инициализирует Singleton.value, но замещается вторым потоком прям перед вызовом MemoryBarrier(). Второй поток проверяет Singleton.value, его значение уже не null, и оно тут-же возвращается из функции. Далее второй поток пытается использовать тот объект Singleton, который он получил, но так как сконструированный объект Singleton еще находится в кэше первого потока (пусть эти потоки выполняются на разных процессорах), то второй поток, думая, что он обращается к памяти Singleton'а, на самом деле читает память, в которой еще мусор. Вот так.


почему мусор? ИМХО, там должен быть 0 — поскольку сброс кэша еще не выполнен, а Singleton.value тоже находится в нем
а в оригинальном варианте есть немаленькая вероятность, что будет выделено несколько объектов singleton (по одному на каждый процессор )
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[6]: Каков механизм write barrier
От: Блудов Павел Россия  
Дата: 31.05.04 05:40
Оценка: 27 (1)
Здравствуйте, Дарней, Вы писали:

Д>почему мусор? ИМХО, там должен быть 0 — поскольку сброс кэша еще не выполнен, а Singleton.value тоже находится в нем\]


Конечно, там не мусор. Другое дело, что конструктор Singleton'а тоже может что-то писать в память.
И тут-то начинается чехарда. В IA32, где Strong Memory Model все нормально.

У IA64 (и CRL) все плохо — Weak Memory Model, т.е процессор _не_обязан_ класть в память сначала
переменные, проинициализированные в конструкторе Singleton'а, а потом его самого. Пример:

 public Singleton {
     this.str = new string("blabla");
 }
 public static Singleton Value {
    get {
        if (Singleton.value == null) {
            lock (syncRoot) {
                if (Singleton.value == null) {
                    Singleton newVal = new Singleton();
                    Singleton.value = newVal;
                }
            }
        }
        return Singleton.value;
    }
}


Тут у IA64 в какой-то момент времени Singleton.value уже перешел из кеша процессора в память,
а Singleton.str еще null!!! Хотя конструктор уже отработал
Такое может произойти, если
1. Процессоров больше чем один
2. Singleton.value и Singleton.str окажутся в разных страницах памяти.
3. Со страницей памяти Singleton.str работает другой процессор.

Вот этот самый другой процессор может словить Singleton.value != null и Singleton.str == null.

Д>есть немаленькая вероятность, что будет выделено несколько объектов singleton (по одному на каждый процессор )

Нулевая. Ну-ле-ва-я. Об этом позаботится

            lock (syncRoot) {
                        }
[c#]

Замечу, что если переписать код вот так:

[c#]
 public static Singleton Value {
    get {
        lock (syncRoot) {
            if (Singleton.value == null) {
                Singleton newVal = new Singleton();
                Singleton.value = newVal;
            }
        }
        return Singleton.value;
    }
}


То все будет очень даже корректно и для IA64 и для IA32.

Павел.
P.S. Еще вопросы?
... << RSDN@Home 1.1.3 beta 2 >>
Re[7]: Каков механизм write barrier
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 31.05.04 06:44
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

БП>Замечу, что если переписать код вот так:


БП>
БП> public static Singleton Value {
БП>    get {
БП>        lock (syncRoot) {
БП>            if (Singleton.value == null) {
БП>                Singleton newVal = new Singleton();
БП>                Singleton.value = newVal;
БП>            }
БП>        }
БП>        return Singleton.value;
БП>    }
БП>}
БП>


БП>То все будет очень даже корректно и для IA64 и для IA32.


Вот только сильно медленнее.
... << RSDN@Home 1.1.4 beta 1 >>
AVK Blog
Re[6]: Каков механизм write barrier
От: alexkro  
Дата: 31.05.04 19:03
Оценка: 27 (1)
Здравствуйте, Дарней, Вы писали:

Д>Здравствуйте, alexkro, Вы писали:


A>>Допустим, делается так как ты предлагаешь. Тогда есть следующий вариант развития событий: первый поток входит в lock выделяет Singleton и инициализирует Singleton.value, но замещается вторым потоком прям перед вызовом MemoryBarrier(). Второй поток проверяет Singleton.value, его значение уже не null, и оно тут-же возвращается из функции. Далее второй поток пытается использовать тот объект Singleton, который он получил, но так как сконструированный объект Singleton еще находится в кэше первого потока (пусть эти потоки выполняются на разных процессорах), то второй поток, думая, что он обращается к памяти Singleton'а, на самом деле читает память, в которой еще мусор. Вот так.


Д>почему мусор? ИМХО, там должен быть 0 — поскольку сброс кэша еще не выполнен, а Singleton.value тоже находится в нем


Ты не понял модель памяти CLR. Запись в память для переменных, доступных глобально, является release. Значит присвоение Singleton.value сразу видимо для всех потоков. А вот сам объект — нет. Это я и имею в виду. На месте объекта для другого потока ещё сырая память — мусор.

Д>а в оригинальном варианте есть немаленькая вероятность, что будет выделено несколько объектов singleton (по одному на каждый процессор )


Нет. В оригинальном варианте тот же самый случай: Singleton.value проинициализирован, а сам объект — нет.
Re[7]: Каков механизм write barrier
От: alexkro  
Дата: 31.05.04 19:11
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

БП>И тут-то начинается чехарда. В IA32, где Strong Memory Model все нормально.


Не тут то было. Strong memory model для одного процессора. А если у тебя их восемь: по четыре в hemisphere? Тут-то синхронизация кэшей начинает играть ту же роль, что и перестановка чтения/записи.

БП>У IA64 (и CRL) все плохо — Weak Memory Model, т.е процессор _не_обязан_ класть в память сначала


У CLR есть своя модель памяти. На IA64 она не будет weak.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.