powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Lock-free: Доведём очередь до ума
147 сообщений из 147, показаны все 6 страниц
Lock-free: Доведём очередь до ума
    #39548674
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Опять не дают мне покоя lock-free алгоритмы, опять немного почитал статьи на Хабре, и опять толком ничего не осилил
В первую очередь меня интересует очередь. Я пытался портировать на Delphi такую реализацию очереди (раздел "Пример использования tagged pointers")

Реализация не взлетела. Может быть я некорректно её переписал, но вот на что я обратил внимание, и что меня не устроило
Смотрите строку D11 ("Читаем значение перед CAS, так как иначе другой dequeue может освободить next")
Т.е. получается, может случиться ситуация, когда в одном потоке произойдёт копирование данных в результат, а другой поток будет финализировать эти данные. Если речь идёт о простых типах - Integer, Pointer и т.д. - то проблем нет. Но если происходит работа с Interface, Variant или строки - ошибка гарантирована.

В общем основы
Очередь представляет собой односвязный список от Head до Tail
Dequeue извлекает элементы из Head, Enqueue добавляет элементы в Tail
НО. Если Dequeue последнего элемента (Head = Tail) - то обнуляются оба указателя
Если Enqueue самого первого элемента (Head = Tail = nil) - то Head тоже инициализируется


В общем я целую неделю опробывал разные подходы с разной результативностью
Основная проблема возникает тогда, когда мы добавляем элементы и ориентируемся на Tail, а Tail тем временем удаляется в другом потоке

В итоге наибольшей стабильности я добился сегодня, когда стал исповедовать правило "кто Tail меняет - тот и задаёт правила"
И мои внутренние тесты показали почти идеальный вариант. Только изредка терялся 1 элемент
Сейчас я ещё больше упростил код, убрав "Tagged pointer" из Next-тов и FTail. Ошибок стало появляться больше. То ли из-за более интенсивной конкуренции, то ли из-за ABA.
Представляю на ваш суд свой код, содержащий ошибки ( есть открытый репозиторий ). Надеюсь, вы свежим взглядом поможете делу

P.S. Да, TSyncPointer - это некий "Tagged pointer", 8 байтовая структура, содержащая указатель и счётчик замен (обычно используется для избежания ABA)

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
  TSyncQueue<T> = class(TSyncObject, ISyncQueue<T>)
  private
    FHead: TSyncPointer;
    FTail: Pointer;

    type
      TNode = TAllocatorNode<Pointer,TNothing,T>;
      PNode = ^TNode;

    function GetEmpty: Boolean; inline;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Clear;

    function Enqueue(const Value: T): Boolean;
    function Dequeue(var Value: T): Boolean;

    property Empty: Boolean read GetEmpty;
  end;


function TSyncQueue<T>.Enqueue(const Value: T): Boolean;
var
  Node, Tail: PNode;
begin
  // новый узел
  Node := TSyncAllocator<Pointer,TNothing,T>.New;
  Node.Value := Value;
  Node.Next := nil;

  // подменяем FTail на узел
  Tail := AtomicExchange(FTail, Node);

  // инициализируем Next предущего узла или сам FHead
  if (Tail = nil) then
  begin
    FHead.Value := Node;
  end else
  begin
    Tail.Next := Node;
  end;
end;

function TSyncQueue<T>.Dequeue(var Value: T): Boolean;
var
  Head: TSyncPointer;
  Tail, Next: Pointer;
begin
  repeat
    Tail := FTail;
    Head := FHead.Copy;

    if (Head.Empty) then
    begin
      // очередь пустая если Tail пустой - выходим
      // может быть задан Tail, а Head ещё не проинициализирован корректным значением
      if (Tail = nil) then
        Exit(False);
    end else
    begin
      // заменяем FHead на Next, при необходимости заменяем FTail
      // Next пустой если ещё не инициализирован (ждём) или последний (обнуляем FTail)
      Next := PNode(Head.Value).Next;
      if (Next = nil) then
      begin
        if (Head.Value = Tail) then
        begin
          // извлекаем единственный элемент - обнуляем FTail
          // и по возможности обнуляем FHead
          if (AtomicCmpExchange(FTail, nil, Tail) = Tail) then
          begin
            FHead.AtomicCmpExchange(nil, Head);
            Break;
          end;
        end else
        begin
          // Next не инициализирован
          // просто ждём
        end;
      end else
      begin
        // Next содержит валидный указатель на следующий узел - кладём его в FHead
        if (FHead.AtomicCmpExchange(Next, Head)) then
          Break;
      end;
    end;
  until (False);

  // результат
  Value := PNode(Head.Value).Value;
  TSyncAllocator<Pointer,TNothing,T>.Dispose(Head.Value);
  Result := True;
end;

...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548677
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

Твой код не осилил (не хочу заморачиваться с пониманием новомодных конструкций), но это не важно.
У меня к тебе вопрос.
Ты уверен, что возможно обойтись без блокировок при добавлении/чтении(взятии в обработку элемента) очереди?
Это единственная блокировка, которая нужна, а затраты на нее несравнимо меньше, чем на обработку элемента очереди, зачастую.
Я лично не уверен. Впрочем, могу ошибаться - мало ли что можно понимать под очередью.

Ну просто по логике. Из разных потоков идет добавление в ОДИН список заданий. Ну как может не быть синхронизации этого добавления (и удаления).
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548678
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,

Уверен :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548680
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockИз разных потоков идет добавление в ОДИН список заданий. Ну как может не быть синхронизации этого добавления (и удаления).
AtomicCmpExchange
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548681
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,
На многопроцессорных системах в большинстве случаев LockFree выигрывает у блокировочных алгоритмов. Блокировка это уровень ядра и это затраты на переключение контекста между потоками. В lockfree такие переключения сведены к минимуму т.к. вся суть в атомарных операциях процессора.

Для программ выполняющихся на компьютерах с 1 процессором такие алгоритмы бессмысленны.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548715
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-CiteYuRock,
На многопроцессорных системах в большинстве случаев LockFree выигрывает у блокировочных алгоритмов. Блокировка это уровень ядра и это затраты на переключение контекста между потоками. В lockfree такие переключения сведены к минимуму т.к. вся суть в атомарных операциях процессора.
тут очень спорно, та же критическая секция в ядро далеко не сразу не уходит


SOFT FOR YOU, на первый взгляд проблема в том, что не отслеживается версионность выделенного участка памяти, элемент может пролететь несколько раз по цепочке контейнер-аллокатор, и это логически будет уже "другой" элемент.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548720
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

кроме того, надо ещё иногда устранять "гонки"

как вариант (мидийная пауза говорят круче)
Код: pascal
1.
2.
3.
4.
5.
procedure SwitchToNextThread(); inline;
begin
  if (not Winapi.Windows.SwitchToThread()) then
    Winapi.Windows.Sleep(1);
end;



очень существенно ускоряет + проц в пиках не загружается на 100%
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
  TBitLock = record
    BitSet: Integer;
  private
    class procedure Test; static;
  public
    function LockFirstZerro(): Integer; overload; inline;
    function LockFirstZerro(From: Integer): Integer; overload; inline;
    function LockFirstBit(): Integer; overload; inline;
    function LockFirstBit(From: Integer): Integer; overload; inline;
    procedure InverseBit(k: Integer); inline;
    procedure Zerro; inline;
  end;

function TBitLock.LockFirstBit(): Integer;
var
  tmp, a, v: LongWord;
begin
  v := LongWord(BitSet);
  repeat
    tmp := v;
    if tmp = 0 then
      Exit(-1);
    a := (not(tmp - 1)) and tmp;
    v := LongWord(TMyInterlocked.CompareExchange(BitSet, Integer(a xor tmp), Integer(tmp)));
    if (v = tmp) then
      break;

    tmp := v;
    if tmp = 0 then
      Exit(-1);
    a := (not(tmp - 1)) and tmp;
    v := LongWord(TMyInterlocked.CompareExchange(BitSet, Integer(a xor tmp), Integer(tmp)));
    if (v = tmp) then
      break;

    tmp := v;
    if tmp = 0 then
      Exit(-1);
    a := (not(tmp - 1)) and tmp;
    v := LongWord(TMyInterlocked.CompareExchange(BitSet, Integer(a xor tmp), Integer(tmp)));
    if (v = tmp) then
      break;

    SwitchToNextThread();
  until False;
  Result := Trunc(Log2(a));
end;

...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548767
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Версионность есть в FHead. Этого недостаточно?
Приведи пример, где может возникнуть ABA
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548769
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Да, будут бэкофы позже.
Но сейчас вопрос не в них, а в корректностям алгоритма
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548771
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Почему Sleep(1)? Передача неиспользованной части кванта это Sleep(0);
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548782
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Версионность есть в FHead. Этого недостаточно?
Приведи пример, где может возникнуть ABAя на вскидку не скажу, надо всё тестить, а это очень долго

вот это тоже косяк - промежуточное состояние не должно блокировать объект, пользуйся только CAS
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
function TSyncQueue<T>.Enqueue(const Value: T): Boolean;
var
  Node, Tail: PNode;
begin
  // новый узел
  Node := TSyncAllocator<Pointer,TNothing,T>.New;
  Node.Value := Value;
  Node.Next := nil;

  // подмен€ем FTail на узел
  Tail := AtomicExchange(FTail, Node); // вот здесь получишь затык всей очереди - если после этой команды произойдёт переключение потока

  // инициализируем Next предущего узла или сам FHead
  if (Tail = nil) then
  begin
    FHead.Value := Node;
  end else
  begin
    Tail.Next := Node;
  end;
end;




в догонку:
зря ассемблерные вставки наделал, лучше маленько да лучше, TInterlocked из SyncObjs покроет все твои потребности в CAS


методы вроде вот этого
Код: pascal
1.
 property Empty: Boolean

бесполезны
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548819
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexeykealon(Ruslan),

Почему Sleep(1)? Передача неиспользованной части кванта это Sleep(0);хз, но так быстрее выходило
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548862
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Сейчас «ассемблер» используется только при замене значения FHead. Возможно ты прав, имеет смысл использовать стандартный двойной CAS. Но он многократно использовался, нареканий по нему нет

Empty. Это простое сравнение Value на nil

Sleep. Это типа backoff стратегии. Принято сначала делать ассемблерную команду pause, потом SwitchToThread, потом Sleep(1). Sleep(0) это относительно долгий простой потока. Быстрее он может быть только на синтетических тестах - за счёт минимизации конкуренции. Стандартные блокировочные алгоритмы, по крайней мере на спинлоке - тоже быстрее на синтетических тестах.

Самое важное. Чтение или запись - сами по себе атомарные операции, кроме того они значительно быстрее. Поначалу я ВРОДЕ БЫ использовал атомики, но очередь по прежнему выдавала ошибки. Если можешь привести пример, где очередь сработает некорректно - милости прошу.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548891
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На какой конфигурации железа проходит тестирование. Если несколько процессоров, то могу предположить что не хватает барьеров памяти
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548896
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-Cite,

Так лок-фри он без барьеров вроде работает :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548914
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUSleep. Это типа backoff стратегии. Принято сначала делать ассемблерную команду pause, потом SwitchToThread, потом Sleep(1). Sleep(0) это относительно долгий простой потока
Вообще-то, Sleep(0) это эквивалент SwitchToThread, с разницей лишь в том, что SwitchToThread отдаёт предпочтение "голодающему" потоку. А любое ненулевое значение в Sleep может усыпить поток очень на долго.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548971
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUX-Cite,

Так лок-фри он без барьеров вроде работает :)
Разве?? У каждого процессора свой кеш.. Что будет если 20 процессоров со своими кешами будут непрерывно класть и доставать из очереди элементы. А если это мобильные процессоры, у них слабосвязанный порядок инструкций.
P.s. я не вижу в enqueue while true... Разве в строке
//подменяем FTail на узел - если 20 нитей будут класть не будет ли потери ftail ??? Вроде как вездедолжен быть while true + cas
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39548975
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ведь суть lockfree это бесконечная попытка чего-либо за конечное число итераций.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549028
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatYuRockИз разных потоков идет добавление в ОДИН список заданий. Ну как может не быть синхронизации этого добавления (и удаления).
AtomicCmpExchange
А работает эта функция (в винде) уж не через InterlockedExchange ли?
А то о ней Майкросовт пишет так: function prevents more than one thread from using the same variable simultaneously.
Перевод: функция предотвращает одновременное использование одной и той же переменной несколькими потоками .

Какими средствами это достигается - объектами ядра или спец. командами процессора (или ф-циями, которые их вызывают) - я вообще-то не уточнял. Я о логике говорил (ты это слово не процитировал). А смысл один - синхронный доступ к списку заданий.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549170
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторThis function is implemented using a compiler intrinsic where possible. For more information, see the WinBase.h header file and _InterlockedExchange.

This function generates a full memory barrier (or fence) to ensure that memory operations are completed in order.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549212
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребят, давайте ближе к теме
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549257
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

а почему FTail не защищен от ABA?

Допустим, поток надолго засыпает в Dequeue прямо перед оператором
if (AtomicCmpExchange(FTail, nil, Tail) = Tail) then

За то время, пока он спал, очередь переходит в другое состояние,
в ней уже 100500 элементов, причем последний сидит по тому же адресу.

Этот if успешно выполнится, но из очереди будет взят последний,
FTail обнулится и последующие Enqueue будут добавлять
в *пустую* с их точки зрения очередь.

Усе пропало, шеф ))
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549314
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Привет :)
Да, наверное ты прав
Скажи, а Node.Next должен быть защищён от ABA или нет?

Ещё момент. В Enqueue я подменяю FTail.
Его обязательно делать с инкрементом счётчика или не обязательно?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549315
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если говорить о той реализации, какая есть - то конкуренции за Next вообще нет, он просто инициализируется и читается
Не таит ли такое допущение каких-то неприятных подводных камней?

Но больше всего у меня вопросов по Head
В Enqueue я инициализирую FHead-указатель. Данный код переписывает значение, а счётчик оставляет прежним. Как ты думаешь, где-то это может сыграть неприятную роль?

И подозреваю я, что ошибка кроется как раз здесь. Когда в Enqueue голова просто инициализируется, а в Dequeue меняется атомиком
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549461
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

море литературы на эту тему, зачем изобретать грабли, на которые уже кто-то наступил.

На мой взгляд, чтобы не тратить время впустую имеет смысл соорудить конечный автомат
и погонять его как следует, а уже потом пробовать строго доказать корректность.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549472
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

как его соорудить? (КА)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549490
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)Aleksandr Sharahov,

как его соорудить? (КА)

Построить имитационную модель, описывающую очередь (включая общую память) + 2-3 читающих потока + 2-3 пишущих потока (с их локальными данными).
Определить возможные состояния потоков между операторами, работающими с очередью (включая общую память) + локальные данные.
Определить общее состояние системы как сумму всего.
Прогнать модель по всем возможным переходам состояний системы.
Наткнуться на ошибки при работе очереди и исправить их.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549504
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Теоретиков много и реализаций много. Для Delphi я видел только одну реализацию (два стека, инверсия) и мне этот вариант не нравится непрогнозируемостью времени исполнения. Есть в Tail накопится 100500 элементов, то при Dequeue бог знает, сколько займёт инверсия.

Не факт, что теорию ты грамотно реализуешь на Delphi. Или в теории нет ошибок. Или в реализации на другом языке. Вон, с точки зрения теории, мой вариант прекрасен. Однако где-то закралась ошибка (и).

Ну или вот реализация MSQueue от автора известной lock-free библиотеки libcds. Однако, его реализация не подходит для менейджед-типов (описал в первом посте почему)

Я тебя спросил (как и всех впрочем), потому что у тебя глаз не замылен. И могут появиться идеи )
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549505
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, тестовое приложение, где два пишущих потока и два читающих - есть (в репозитории )
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549576
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUреализация MSQueue от автора известной lock-free библиотеки libcds ... не подходит для менейджед-типов (описал в первом посте почему)


Честно говоря, не понял, почему оно не должно работать для указателя на строку.
Кто строку юзает, тот ее и освобождает )
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549580
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUДля Delphi я видел только одну реализациюGpLockFreeQueue, OTL смотрел?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549626
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
vavanSOFT FOR YOUДля Delphi я видел только одну реализациюGpLockFreeQueue, OTL смотрел?
первое я ему уже подкидывал, когда он ещё супер-пупер-мега-менеджер памяти делал
чем-то не подошло ему
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549639
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Строка D11
Пока один поток копирует строку, второй поток может её удалить

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
procedure _UStrAsg(var Dest: UnicodeString; const Source: UnicodeString);
var
  S, D: Pointer;
  P: PStrRec;
  Len: Integer;
begin
  S := Pointer(Source);
  if S <> nil then
  begin
    if __StringRefCnt(Source) < 0 then   // make copy of string literal
    begin
      Len := __StringLength(Source);
      S := _NewUnicodeString(Len);
      Move(Pointer(Source)^, S^, Len * SizeOf(WideChar));
    end else
    begin
      P := PStrRec(PByte(S) - SizeOf(StrRec));
      AtomicIncrement(P.refCnt);
    end;
  end;
  D := Pointer(Dest);
  Pointer(Dest) := S;
  _UStrClr(D);
end;

function _UStrClr(var S): Pointer;
var
  P: PStrRec;
begin
  if Pointer(S) <> nil then
  begin
    P := Pointer(PByte(S) - SizeOf(StrRec));
    Pointer(S) := nil;
    if P.refCnt > 0 then
    begin
      if AtomicDecrement(P.refCnt) = 0 then
        FreeMem(P);
    end;
  end;
  Result := @S;
end;



Поток A читает валидный указатель-строку
Поток B освобождает валидую строку
Поток А обращается к несуществующей области памяти
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549650
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUAleksandr Sharahov,
Строка D11
Пока один поток копирует строку, второй поток может её удалить
...
Поток A читает валидный указатель-строку
Поток B освобождает валидую строку
Поток А обращается к несуществующей области памяти

1. Я там не вижу строку D11.
2. Зачем они это делают? Почему вместо того, чтобы работать с *указателем* на строку, они работают со строкой? К работе со строкой надо переходить, когда есть полная уверенность в успешном извлечении данных из очереди. В нашем случае это указатель на данные. Его-то можно безопасно извлечь.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549656
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vavanSOFT FOR YOUДля Delphi я видел только одну реализациюGpLockFreeQueue, OTL смотрел?

Смотрел
Если я правильно понял, его реализация - имеет ограничение на количество элементов. А я хочу без ограничения
Кроме того, он там сильно заморочился на теги, много атомиков
В данной реализации должно быть быстрее
Когда ошибку найдём
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549665
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Строку D11 надо смотреть здесь :)
У них видимо данные не менаджатся и данная реализация устраивает
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549674
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

И в чем проблема? Указатели нельзя копировать?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549676
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Ну если ты пишешь шаблоны - то копирование происходит просто Value := Node.Value. А финализация Finalize(Node.Value)
Строку я привёл в качестве примера. Это может быть структура, содержащая строки, интерфейсы и динамические массивы. Или вообще Weak экземпляры классов :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549684
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати я избавился от ассемблера, заменил FTail на "tagged pointer"
Сейчас работает стабильнее, но ошибки всё равно детектятся:
Код: plaintext
1.
2.
Элемент 9975462 изъят больше одного раза
Элемент 9975465 потерян
Элемент 9975466 потерян

Код теперь выглядит так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
function TSyncQueue<T>.Enqueue(const Value: T): Boolean;
var
  Node: PNode;
  Tail: TSyncPointer;
begin
  // новый узел
  Node := TSyncAllocator<Pointer,TNothing,T>.New;
  Node.Value := Value;
  Node.Next := nil;

  // подменяем FTail на узел
  Tail := FTail.AtomicExchange(Node);

  // инициализируем Next предущего узла или сам FHead
  if (Tail.Empty) then
  begin
    FHead.Value := Node;
  end else
  begin
    PNode(Tail.Value).Next := Node;
  end;
end;

function TSyncQueue<T>.Dequeue(var Value: T): Boolean;
var
  Head, Tail: TSyncPointer;
  Next: Pointer;
begin
  repeat
    Tail := FTail.Copy;
    Head := FHead.Copy;

    if (Head.Empty) then
    begin
      // очередь пустая если Tail пустой - выходим
      // может быть задан Tail, а Head ещё не проинициализирован корректным значением
      if (Tail.Empty) then
        Exit(False);
    end else
    begin
      // заменяем FHead на Next, при необходимости заменяем FTail
      // Next пустой если ещё не инициализирован (ждём) или последний (обнуляем FTail)
      Next := PNode(Head.Value).Next;
      if (Next = nil) then
      begin
        if (Head.Value = Tail.Value) then
        begin
          // извлекаем единственный элемент - обнуляем FTail
          // и по возможности обнуляем FHead
          if (FTail.AtomicCmpExchange(nil, Tail)) then
          begin
            FHead.AtomicCmpExchange(nil, Head);
            Break;
          end;
        end else
        begin
          // Next не инициализирован
          // просто ждём
        end;
      end else
      begin
        // Next содержит валидный указатель на следующий узел - кладём его в FHead
        if (FHead.AtomicCmpExchange(Next, Head)) then
          Break;
      end;
    end;
  until (False);

  // результат
  Value := PNode(Head.Value).Value;
  TSyncAllocator<Pointer,TNothing,T>.Dispose(Head.Value);
  Result := True;
end;

...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549687
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

Правильные пацаны помещают в очередь указатели на свои структуры данных.

А ты экономишь одну загрузку адреса, и поэтому их реализация тебе не подходит.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549691
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUAleksandr Sharahov,

Ну если ты пишешь шаблоны - то копирование происходит просто Value := Node.Value. А финализация Finalize(Node.Value)
Строку я привёл в качестве примера. Это может быть структура, содержащая строки, интерфейсы и динамические массивы. Или вообще Weak экземпляры классов :)

Финализировать раздельно надо.
Отдельно элемент очереди.
И отдельно (после разыменования указателя и использования структуры) свою структуру данных.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549704
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Персона Иванов ИИ обладает фамилией, именем и т.д., но не является элементом очереди. Это объект или запись класса персона.
Иван Иваныч может одновременно стоять в 10 очередях: на квартиру, за зарплатой, на автобус, за хлебом...
Но вместо него в этих очередях стоят адреса.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549707
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Ну во-первых, претензии не ко мне - а к автору статьи :)
Во-вторых, если мы храним указатель, то где-то его нужно выделять и освобождать. Либо должны будем юзать свой ограниченный буфер памяти в виде lock-free стека, что приведёт к лимитированности очереди и дополнительным атомикам, либо будем обращаться к стандартному менеджеру, который синхронизируется критической секцией, со всеми вытекающими. Тем более, для малых типов данных использовать указатель на память в куче - очень расточительно.

Наконец, lock-free алгоритмы являются отличной возможностью поломать голову
И я свою, похоже, сломал
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549710
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

я же тебе уже говорил, Empty и всё такого рода это бессмысленные функции, а она у тебя опять в коде
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549711
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Никто ж не против Иван Иваныча или адресов. Меня интересует общий случай, когда можешь поместить адрес, Иван Иваныча или динамический массив - и все они войдут и выдут из очереди во время
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549713
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

А я тебе говорил, что это сравнение Value на nil. И стоят они там, где нужно проверить Value на nil :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549718
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUAleksandr Sharahov,

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

ну, тогда это действительно серьезный случай )
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549720
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahovkealon(Ruslan)Aleksandr Sharahov,

как его соорудить? (КА)

Построить имитационную модель, описывающую очередь (включая общую память) + 2-3 читающих потока + 2-3 пишущих потока (с их локальными данными).
Определить возможные состояния потоков между операторами, работающими с очередью (включая общую память) + локальные данные.
Определить общее состояние системы как сумму всего.
Прогнать модель по всем возможным переходам состояний системы.
Наткнуться на ошибки при работе очереди и исправить их.
Добавлю, что на однопроцессрной машине бесполезно этим заниматься.. 1 процессор и N ядер не подходят тоже.
От автора статьи так и не дождались его конфигурации ради чего это затевается.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549723
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-CiteДобавлю, что на однопроцессрной машине бесполезно этим заниматься.. 1 процессор и N ядер не подходят тоже.
От автора статьи так и не дождались его конфигурации ради чего это затевается.

На 1 процессоре можно легко сымитировать N-процессорную очередь.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549724
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

На 1 процессорном атомики не будут отваливаться
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549726
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUЕсли я правильно понял, его реализация - имеет ограничение на количество элементову него очередь растет с выделением памяти по мере заполняемости
SOFT FOR YOUА я хочу без ограниченияну такое только на компах без ограничений памяти
SOFT FOR YOUон там сильно заморочилсякаждый делающий lf через это проходит
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549729
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUAleksandr Sharahov,

На 1 процессорном атомики не будут отваливаться

Разумеется, не будут. Потому, что в имитации вообще нет ни одного CASа.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549736
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

А я тебе говорил, что это сравнение Value на nil. И стоят они там, где нужно проверить Value на nil :)

вижу, что не доходит...

пример
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
function TSyncQueue<T>.Enqueue(const Value: T): Boolean;
var
  Node: PNode;
  Tail: TSyncPointer;
begin
  // новый узел
  Node := TSyncAllocator<Pointer,TNothing,T>.New;
  Node.Value := Value;
  Node.Next := nil;

  // подменяем FTail на узел
  Tail := FTail.AtomicExchange(Node);

  // инициализируем Next предущего узла или сам FHead
  if (Tail.Empty) then
  begin
    sleep(3); 
    FHead.Value := Node;
  end else
  begin
    PNode(Tail.Value).Next := Node;
  end;
end;



так работает?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549757
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)так работает?

Так работает, даже лучше . По крайней мере повторить ошибку не смог :)
Тебя здесь смущает наверное не Tail.Empty, а FHead.Value := Node
И ты прав, это место достойно более пристального внимания. Но из-за счётчика в FHead, а не из-за сравнения Tail на nil

В данном коде Tail играет роль не текущего хвоста, и хвоста, который был раньше
Т.е. если раньше хвост был пустой (очередь пустая) - FHead тоже инициализируем только что добавленным узлом
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549783
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan)так работает?

Так работает, даже лучше . По крайней мере повторить ошибку не смог :)
Тебя здесь смущает наверное не Tail.Empty, а FHead.Value := Node
И ты прав, это место достойно более пристального внимания. Но из-за счётчика в FHead, а не из-за сравнения Tail на nil

В данном коде Tail играет роль не текущего хвоста, и хвоста, который был раньше
Т.е. если раньше хвост был пустой (очередь пустая) - FHead тоже инициализируем только что добавленным узлом

а ты тест нормальный сделай


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
program TestUG;

{$APPTYPE CONSOLE}

//{$R *.res}

uses
  Winapi.Windows,
  System.SysUtils,
  System.Classes,
  System.Generics.Collections,
  LockFree in 'LockFree.pas';

type
  // поток, добавл€ющий элементы в очередь
  TEmissionThread = class(TThread)
  protected
    procedure Execute; override;
  end;


var
  i: Integer;
  Threads: TObjectList<TThread>;

  Q: TSyncQueue<Integer>;

procedure TEmissionThread.Execute;
var
  Value: Integer;
begin
  while (not Terminated) do
  begin
    Q.Enqueue(3);
    if not Q.Dequeue(Value) then
      raise Exception.Create('Error Message');
  end;
end;

begin
  try
    Q := TSyncQueue<Integer>.Create();
    try
      Threads:= TObjectList<TThread>.Create;
      try
        // инициализируем потоки
        for i := 1 to 5 do
          Threads.Add(TEmissionThread.Create);

        Writeln;
        Write('Press Enter to quit');
        Readln;
      finally
        Threads.Free;
      end;
    finally
      Q.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.



всегда забитая очередь никому не нужна
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549796
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Не очень понятно, что ты хотел показать этим тестом
Ошибок найдено не было
Ожидание потоков ты не делаешь
Проверок ты не делаешь

Возможно ты хотел указать на случай, когда Dequeue будет простаивать в ожидании инициализации
Но точно такой же "Sleep" может возникнуть во время Dequeue и очередь будет долго расти в Tail
В любом случае никакого отношения это к Empty не имеет
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549812
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUПроверок ты не делаешь
хочешь сказать, что у тебя эксепшн не срабатывает?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549822
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Нет
А у тебя?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549826
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Нет
А у тебя?практически моментально
i7-4710HQ
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549832
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Выложи тест полностью и какая версия Delphi
Потому что Dequeue не должен вернуть False

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    Tail := FTail.Copy;
    Head := FHead.Copy;

    if (Head.Empty) then
    begin
      // очередь пустая если Tail пустой - выходим
      // может быть задан Tail, а Head ещё не проинициализирован корректным значением
      if (Tail.Empty) then
        Exit(False);
    end



Если выполнился Enqueue - то FTail не должен быть пустым
Код: pascal
1.
2.
3.
4.
5.
6.
7.
  // новый узел
  Node := TSyncAllocator<Pointer,TNothing,T>.New;
  Node.Value := Value;
  Node.Next := nil;

  // подменяем FTail на узел
  Tail := FTail.AtomicExchange(Node);
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549838
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

20937473 - он весь и есть, модуль с репа твоего
Delphi Xe 10.2

>>Потому что Dequeue не должен вернуть False
это и проверяется, про эту ошибку я тебе уже писал - 20931687 ( - промежуточное состояние не должно блокировать объект, пользуйся только CAS )
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549842
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Не, давай для чистоты эксперимента выкладывай все файлы
Заодно народ у себя потестит
Пока возникает ощущение, что ты в модулях как-то не то поправил :)

И да
Опиши модель на примере потоков A и B, как это могло произойти
Ибо запись и чтение (GetEmpty) - сами по себе атомарные операции. Если память выровнена. А она должны быть выровнена
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549843
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Не, давай для чистоты эксперимента выкладывай все файлы
Заодно народ у себя потестит
Пока возникает ощущение, что ты в модулях как-то не то поправил :)

И да
Опиши модель на примере потоков A и B, как это могло произойти
Ибо запись и чтение (GetEmpty) - сами по себе атомарные операции. Если память выровнена. А она должны быть выровнена

вот Фома неверующий

некогда, нет у меня столько свободного времени
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549852
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребята, потестируйте, пожалуйста, пример выше
У меня Exception не воспроизводится (i3-6100U)
Если воспроизведётся - давайте подумаем, почему

kealon(Ruslan),

А мой тест у тебя проходит?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549868
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

код не смотрел, но осуждаю. Чем докажешь, что операторы из кода в начале темы

Tail.Next := Node;
и
Next := PNode(Head.Value).Next;

обращаются по валидным адресам?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549872
Andy Mezentsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUРебята, потестируйте, пожалуйста, пример выше
У меня Exception не воспроизводится (i3-6100U)
Если воспроизведётся - давайте подумаем, почему

kealon(Ruslan),

А мой тест у тебя проходит?

Коллеги, какая Delphi нужна? на 2010 не собирается :(
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549874
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andy MezentsevКоллеги, какая Delphi нужна? на 2010 не собирается :(
Delphi Xe 10.2 точно собирает

SOFT FOR YOUРебята, потестируйте, пожалуйста, пример выше
У меня Exception не воспроизводится (i3-6100U)
Если воспроизведётся - давайте подумаем, почему

kealon(Ruslan),

А мой тест у тебя проходит?
не прошёл на 4-й раз
Код: plaintext
1.
2.
3.
Элемент 10000000 потерян

Press Enter to quit
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549878
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Очень хорошие вопросы
Давай разбираться

> Tail.Next := Node;

Это стало быть Enqueue
Единственное место, где могут получить доступ к этому узлу из другого потока - Dequeue
Важной особенностью этого узла является то, что Next у этого узла всегда равен nil

В Dequeue же анализируется Next узла
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
      // заменяем FHead на Next, при необходимости заменяем FTail
      // Next пустой если ещё не инициализирован (ждём) или последний (обнуляем FTail)
      Next := PNode(Head.Value).Next;
      if (Next = nil) then
      begin
        if (Head.Value = Tail.Value) then
        begin
          // извлекаем единственный элемент - обнуляем FTail
          // и по возможности обнуляем FHead
          if (FTail.AtomicCmpExchange(nil, Tail)) then
          begin
            FHead.AtomicCmpExchange(nil, Head);
            Break;
          end;
        end else
        begin
          // Next не инициализирован
          // просто ждём
        end;
      end



> Next := PNode(Head.Value).Next

Это уже Dequeue
На данный момент кто-то уже мог удалить элемент из очереди, и в Next будет содержаться мусор, вполне вероятно nil
Однако, если Head уже невалидный, то FHead.AtomicCmpExchange(Next, Head) не пройдёт и цикл уйдёт на следующую итерацию

Может быть возможен сценарий, когда в невалидном Head лежит ложный nil и это приводит к ошибке логики очереди?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549879
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andy Mezentsev,

Я тестирую минимум на XE3
Может быть на первом заведётся
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549882
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUОднако, если Head уже невалидный, то...

дальше можно не продолжать )
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549886
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUAndy Mezentsev,

Я тестирую минимум на XE3
Может быть на первом заведётсяна XE2 уже не компилится
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549900
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)SOFT FOR YOUAndy Mezentsev,

Я тестирую минимум на XE3
Может быть на первом заведётсяна XE2 уже не компилится

Да, дженерики на Дельфях, и особенно старых компиляторах, оставляют желать лучшего.
Их приходится допиливать наждаком с упоминанием какой-то матери :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549901
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr SharahovSOFT FOR YOUОднако, если Head уже невалидный, то...

дальше можно не продолжать )

Ну а чего ты хотел :)
Весь lock-free построен на том, что что-то валидно, а что-то уже нет
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549907
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUНу а чего ты хотел :)
Весь lock-free построен на том, что что-то валидно, а что-то уже нет

не только весь lock-free, но еще и весь BrainMM )
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549908
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
SOFT FOR YOUkealon(Ruslan)пропущено...
на XE2 уже не компилится

Да, дженерики на Дельфях, и особенно старых компиляторах, оставляют желать лучшего.
Их приходится допиливать наждаком с упоминанием какой-то матери :)
дженерики зло.
попробуй сделать так, чтобы они не понадобились
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549924
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Да, BrainMM использует стек
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549931
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUРебята, потестируйте, пожалуйста, пример выше
У меня Exception не воспроизводится (i3-6100U)
Если воспроизведётся - давайте подумаем, почему

kealon(Ruslan),

А мой тест у тебя проходит?повторяется уже на 2-х потоках (так что по идее у тебя должен ловиться)

либо зависает
Код: pascal
1.
2.
3.
4.
5.
6.
7.
function TSyncQueue<T>.Dequeue(var Value: T): Boolean;
var
  Head, Tail: TSyncPointer;
  Next: Pointer;
begin
  repeat
     .... вот из этого цикла выйти не может
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549936
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У кого идея сценария, при котором может возникнуть ошибка
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549941
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

у меня идея не пытаться работать с данными по инвалидным адресам
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549944
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

Может стоит по пробовать другие алгоритмы. Интересная статья
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549952
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Адреса валидные
Данные невалидны

Даже если взять стек (псевдокод):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
while (True) do
begin
  Value := Head;
  if (Value = nil) then Exit(nil);
  Next := Value.Next; // <--
  if CAS(Head, Next) then Exit(Value)
end;



Даже в случае стека ты не можешь однозначно судить, внутри Value значение Next валидное, или это мусор
Value корректный только в том случае, если CAS прошёл успешно
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39549953
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Там нет очереди
Да и смысл
Ты здесь найди ошибку :). А то будешь всё время подсматривать у других :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550027
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUАдреса валидные
Данные невалидны


Адрес перестает быть валидным, как только ты отдал его менеджеру памяти.

Это уже не твой адрес, это его адрес.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550034
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Там нет очереди
Да и смысл
Ты здесь найди ошибку :). А то будешь всё время подсматривать у других :)
ошибка у тебя уже есть - 20937825
я уже прошёл твой этап - и поискал уже прилично в своём коде, потому и говорю тебе про ошибки в твоём коде, которые ты упорно не признаёшь.

красной тряпкой служат такие вещи:
IntelockedExchange

IsEmpty и похожие на них
Я плохой учитель, я не могу на пальцах объяснить почему так, это наверное что-то должно сдвинуться у обучаемого.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550038
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Существуют разные теории, как работать с памятью, чтобы при обращении по адресу не возник AV. Сейчас сделан общий пул в зависимости от размера. Ранее выделенные объекты больше не возвращаются менеджеру памяти. Фактически есть стек наших объектов и в Next хранится указатель на следующий объект. И да, он может быть равен nil.

Если Head успели удалить, а я считаю Next валидным - то AtomicCmpExchange не пройдёт
Если же Next равен nil - то всё равно значение (сам указатель) не должен быть равен Tail
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550041
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

То что ты приводишь - это предположения
Озвучь сценарий, при котором возможна некорректная работа алгоритма
Это и будет весомым аргументом
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550047
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

То что ты приводишь - это предположения
Озвучь сценарий, при котором возможна некорректная работа алгоритма
Это и будет весомым аргументом

по простому, по красным тряпкам

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
function TSyncQueue<T>.Enqueue(const Value: T): Boolean;
var
  Node: PNode;
  Tail: TSyncPointer;
begin
  // новый узел
  Node := TSyncAllocator<Pointer,TNothing,T>.New;
  Node.Value := Value;
  Node.Next := nil;

  // подмен€ем FTail на узел
  Tail := FTail.AtomicExchange(Node);
  // приехал, твоя очередь разорвана, когда она восстановитcя - вопрос
 




Код: pascal
1.
2.
3.
4.
  // инициализируем Next предущего узла или сам FHead
  if (Tail.Empty) then  // пока это проверяешь состояние может стать другим, т.е. играешь в теорию вероятности. 
 
   



так доступно?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550051
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

> приехал, твоя очередь разорвана, когда она восстановитcя - вопрос

Да, очередь разорвана
Потому что мы имеем не с одним указателем, а сразу с двумя
В рамках lock-free иначе ты не сделаешь, в любом случае будет некое промежуточное состояние, которое будет тормозить либо извлечение, либо добавление

> if (Tail.Empty) then // пока это проверяешь состояние может стать другим, т.е. играешь в теорию вероятности.

Не интересно состояние, которое будет потом
В любом случае очередь разорвана и мы должны восстановить связи
Tail в данном случае это узел, который был до Enqueue
И либо в его Next мы прописываем узел, либо инициализируем FHead
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550052
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"Среди кустарей с мотором, которыми изобиловал Старгород, он был самым непроворным и наиболее часто попадавшим впросак. Причиной к этому служила его чрезмерно кипучая натура. Это был кипучий лентяй. Он постоянно пенился. В собственной его мастерской, помещавшейся во втором дворе дома № 7 по Перелешинскому переулку, застать его было невозможно. Потухший переносной горн сиротливо стоял посреди каменного сарая, по углам которого были навалены проколотые камеры, рваные протекторы «Треугольник», рыжие замки, такие огромные, что ими можно было запирать города, мятые баки для горючего с надписями «Indian» и «Wanderer», детская рессорная колясочка, навеки заглохшая динамка, гнилые сыромятные ремни, масляная пакля, стертая наждачная бумага, австрийский шт ык и множество рваной, гнутой и давленой дряни.

Заказчики не находили Виктора Михайловича. Виктор Михайлович уже где-то распоряжался. Ему было не до работы. Он не мог видеть спокойно въезжающего в свой или чужой двор ломовика с кладью. Полесов сейчас же выходил во двор и, сложив руки на спине, презрительно наблюдал за действиями возчика. Наконец сердце его не выдерживало.

— Кто же так заезжает? — кричал он, ужасаясь. — Заворачивай! Испуганный возчик заворачивал.

— Куда ж ты заворачиваешь, морда?! — страдал Виктор Михайлович, налетая на лошадь. — Надавали бы тебе в старое время пощечин, тогда бы заворачивал!

Покомандовавши так с полчаса, Полесов собирался было уже возвратиться в мастерскую, где ждал его непочиненный велосипедный насос, но тут спокойная жизнь города обычно вновь нарушалась каким-нибудь недоразумением. То на улице сцеплялись осями телеги, и Виктор Михайлович указывал, как лучше всего и быстрее их расцепить; то меняли телеграфный столб, и Полесов проверял его перпендикулярность к земле собственным, специально вынесенным из мастерской отвесом; то, наконец, устраивалось общее собрание жильцов. Тогда Виктор Михайлович стоял посреди двора и созывал жильцов ударами в железную доску; но на самом собрании ему не удавалось побывать. Проезжал пожарный обоз, и Полесов, взволнованный звуками трубы и испепеляемый огнем беспокойства, бежал за колесницами."

Не могу удержаться.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550076
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schi,

Забанить бы тебя за офтоп :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550095
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

> приехал, твоя очередь разорвана, когда она восстановитcя - вопрос

Да, очередь разорвана
Потому что мы имеем не с одним указателем, а сразу с двумя
В рамках lock-free иначе ты не сделаешь, в любом случае будет некое промежуточное состояние, которое будет тормозить либо извлечение, либо добавление Это не особенность lock-free, это особенность твоего алгоритма. С такой "гарантией" очередь нафиг не нужна - 20937825 . То что ты не знаешь как это сделать, не значит, что это невозможно.
SOFT FOR YOU > if (Tail.Empty) then // пока это проверяешь состояние может стать другим, т.е. играешь в теорию вероятности.

Не интересно состояние, которое будет потом
В любом случае очередь разорвана и мы должны восстановить связи
Tail в данном случае это узел, который был до Enqueue
И либо в его Next мы прописываем узел, либо инициализируем FHeadс lock-free не бывает неважного, просто пока ты не знаешь где неправ.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39550121
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Давай меньше флуда, больше дела
Опиши сценарий, при котором может возникнуть ошибка

К примеру я тебе привожу участки кода, где производится ожидание.
Ожидание - не возвращает False
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
  repeat
    Tail := FTail.Copy;
    Head := FHead.Copy;

    if (Head.Empty) then
    begin
      // очередь пустая если Tail пустой - выходим
      // может быть задан Tail, а Head ещё не проинициализирован корректным значением
      if (Tail.Empty) then
        Exit(False);
    end else
    begin
      // заменяем FHead на Next, при необходимости заменяем FTail
      // Next пустой если ещё не инициализирован (ждём) или последний (обнуляем FTail)
      Next := PNode(Head.Value).Next;
      if (Next = nil) then
      begin
        if (Head.Value = Tail.Value) then
        begin
          ...
        end else
        begin
          // Next не инициализирован
          // просто ждём
        end;
      end 



И да. Будь другом, приведи пример очереди без промежуточных ожиданий. К примеру реализация Otl полна ожидающих стейтов
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39551365
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Запусти, пожалуйста, свой тест с таким классом:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  TQueue = class(TSyncStack<Integer>)
    function Enqueue(const Value: Integer): Boolean;
    function Dequeue(var Value: Integer): Boolean;
  end;

function TQueue.Enqueue(const Value: Integer): Boolean;
begin
  Push(Value);
  Result := True;
end;

function TQueue.Dequeue(var Value: Integer): Boolean;
begin
  Result := Pop(Value);
end;



Хочу убедиться, что проблема не в TSyncPointer
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552445
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мы тут нашли одну ошибку. Когда счётчик FHead не инкрементировался
Сейчас потестируйте, пожалуйста, пример килона
https://bitbucket.org/d-mozulyov/lockfree/src
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552455
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

читаю я эту ветку и вспоминаю твой менеджер памяти. История повторяется один-в-один
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552516
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asutp2,

За тем лишь исключением, что BrainMM уже юзают, а лок фри ещё нет :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552522
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUBrainMM уже юзаютЧто, прям в продакшене? Я бы поостерегся
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552524
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_nigger,

Ну на однопоточных то он не сбоит. Почему бы нет
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552525
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUНу на однопоточных то он не сбоит. Почему бы нет
Так на одноточке от него проку нет, даже по твоим замерам.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552531
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Есть выравнивания, работа со страницами, executable куча
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552533
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Давайте про lock-free всё-таки :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552629
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUДавайте про lock-free всё-таки :)есть у меня одна идейка, гарантированная lock-free очередь на простых принципах, правда с ограничением размера.
Нужно?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552639
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)правда с ограничением размера.
Нужно?едва ли:SOFT FOR YOUЕсли я правильно понял, его реализация - имеет ограничение на количество элементов. А я хочу без ограниченияхоть габр на тесте миллион элементов и заливал, но нужно строго "без ограничения"
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552650
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)есть у меня одна идейка, гарантированная lock-free очередь на простых принципах, правда с ограничением размера.
Нужно?
Выкладывай. Даже если ТСу не нужно - пригодится кому-нибудь другому.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552725
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Я думал, будет ли выгода при кольцевом буфере. И пришёл к выводу, что всё примерно так же - 2 каса на чтение, и столько же на запись. Но в любом случае выложи. Почему нет.

Вообще, самая простая реализация очереди - это два стека. Стек Tail обычный и Head инвертированный.
Но я уже писал, почему не стал строить реализацию на её основе.

А что с ошибками? По прежнему выдаёт эксепшн?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552920
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

https://svn.code.sf.net/p/cl4fpc/code/Containers/lfqueues.pas
есть правда где-то ошибка на x86 c TAtomicInt = UInt64;, найти времени нет, но 32-битная версия пашет как задумано
заправлю потом в бложик описание реализации

тест
https://svn.code.sf.net/p/cl4fpc/code/Containers/test/FreeLockTest.lpr




SOFT FOR YOUА что с ошибками? По прежнему выдаёт эксепшн?
ну если так закрыть конечно нет, но правильно же он от этого не заработает
20945540 ИМХО правильное рассуждение, нужен механизм проверки нахождения элемента в очереди
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39552955
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Код жёсткий :)
Правда, я так и не понял, зачем столько стейтов

По поводу Exception-ов
Я ничего не закрыл. Я сделал инкремент счётчика при записи FHead.
Эксепшны сыпятся или нет?

По поводу поста - я ведь не против, может действительно дело в мусорном значении Next
Но вот незадача - в случае эмуляции контейнера через стек - ошибок не происходит. По крайней мере у меня. А он работает по тому же принципу
Да и придумать вариант, как может возникнуть ошибка - я тоже придумать не могу
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39553129
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Код жёсткий :)
Правда, я так и не понял, зачем столько стейтов
всё очень просто, попытаюсь объяснить в блоге как время будет
PS: баг исправил
SOFT FOR YOUПо поводу Exception-ов
Я ничего не закрыл. Я сделал инкремент счётчика при записи FHead.
Эксепшны сыпятся или нет?

По поводу поста - я ведь не против, может действительно дело в мусорном значении Next
Но вот незадача - в случае эмуляции контейнера через стек - ошибок не происходит. По крайней мере у меня. А он работает по тому же принципу
Да и придумать вариант, как может возникнуть ошибка - я тоже придумать не могу

TestUG не проходит, хотя проработал без сбоев заметно дольше

с заменой 20945254 проходит без проблем вроде как
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39553165
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Спасибо
Конечно интересно почитать блог

Но давай исправим ошибку в моей реализации
А потом замерим производительность :)

Я просто думаю, что контейнеры надо создавать опционально: с лимитированным количеством элементов и нет. Потому как в лимитированных реализациях может быть определённый профит, как с точки зрения функционала, так и с точки зрения производительности.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39553166
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Мне кажется, или у тебя ограничение на количество элементов жёстко - 21?
Кстати DefaultValue можно не хранить, есть "функция" Default(T)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39553265
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Спасибо
Конечно интересно почитать блог

Но давай исправим ошибку в моей реализации
А потом замерим производительность :)

Я просто думаю, что контейнеры надо создавать опционально: с лимитированным количеством элементов и нет. Потому как в лимитированных реализациях может быть определённый профит, как с точки зрения функционала, так и с точки зрения производительности.тут всё довольно просто:
исходя из тестов что я знаю на i7: конкурентно в секунду можно провести 40 млн обменных операций с одной кэш-линейкой
т.е. тупо InterlockedIncrement из 4-х и более потоков можно сделать 40млн/c, в один поток - 150млн/c

представленный алгоритм упирается сейчас в 2.5 млн (добавление + удаление) в секунду
твой (пока работает) - упирается в 3.5 млн (добавление + удаление)/c
тут насколько я их понимаю добились - 16 млн. /c, и в явовской - 4 млн./c (проц вроде бы такой же как и у меня, но с другой стороны хз как они тестят, например забитая очередь явно шустрее идёт, чем близкая к нулю)

т.е. ещё оптимизировать и оптимизировать, наверное, первое - это функцию разгрузки
SOFT FOR YOUkealon(Ruslan),

Мне кажется, или у тебя ограничение на количество элементов жёстко - 21?
Кстати DefaultValue можно не хранить, есть "функция" Default(T)
10 и 21, в зависимости от типа (нужно 3 бита на состояние одной ячейки)
Default(T) - в fpc старой версии её добавить не успели
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39553780
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Всё-таки производительность у AtomicIncrement, AtomicExchange и AtomicCmpExchange разная. Наверняка на 8 байтах картина ещё больше меняется. Я бы не стал обобщать :)

И не совсем ясно как ты замеряешь производительность :)
По первой ссылке стек, он разумеется, выполняется быстрее очереди. Его теста я что-то не увидел
Да и джававского тоже )

Ну и потом, я не уверен на счёт твоей очереди, но вот в моей важно, есть конкуренция за оба поля или нет
Т.е. если ты сначала добавишь 10 элементов, а потом извлечёшь - картинка будет более разумная. Нежели чем гонять один и тот же элемент туда-обратно.
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39553809
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

практически одинаковая для текущей разрядности, во всяком случае на i7 (cmp версии только при успехе считать надо)
у себя проверь, недолго

соответственно при наличии 2-х операций на вставке, 2-х на удалении это 10млн/c максимум для моего проца
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39553919
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

занятную функцию нашёл - WaitOnAddress
по идее для разгрузки самое то
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39554273
_StarikPro_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Народ, разъясните пожалуйста (признаюсь, всю ветку темы ТС не читал), чем не устраивает очередь с кольцевым буфером в котором указатель на тайл читающего и пишущего потоков "не пересекаются " при условии что для обеспечения многопоточности создаём одну очередь на каждую пару потоков??? Соотв-но, к примеру, для одного читающего и N в него пишущих создаём N очередей который опрашивает читающий... При этом отпадает необходимость в применении спец. синхронизирующих системных функций...
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39554489
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_StarikPro_Народ, разъясните пожалуйста (признаюсь, всю ветку темы ТС не читал), чем не устраивает очередь с кольцевым буфером в котором указатель на тайл читающего и пишущего потоков "не пересекаются " при условии что для обеспечения многопоточности создаём одну очередь на каждую пару потоков??? Соотв-но, к примеру, для одного читающего и N в него пишущих создаём N очередей который опрашивает читающий... При этом отпадает необходимость в применении спец. синхронизирующих системных функций...ситуация: 1 читающий, много пишущих - не самая распространённая
одну очередь проще использовать, она становистя слабым местом систем типа акторов, например


вот все и меряются ...
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39554679
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Так он под Windows 8
Лучше тогда уж вручную брейкпоинт на память делать

_StarikPro_,

Мне кажется среди нас дельфистов алгоритмы lock-free вообще не в ходу. Мы о них знаем слишком мало.
Поэтому я целиком и полностью за дискуссии, разные реализации, тесты и поиск ошибок.
О высокой ценности моей реализации сложно судить, пока она выдаёт ошибки иногда.
Лучше давайте сначала найдём ошибку в таком простом коде, а потом будем рассуждать о плюсах и минусах разных реализаций.

Если говорить в теории, то ценность моего решения заключается в нескольких пунктах.
Во-первых, нет явного ограничения на количество элементов в очереди (а в кольцевом есть)
Во-вторых, нет ограничения на количество читающих или пишущих потоков
В-третьих, производительность по идее (если речь не о первом элементе в очереди) на высоком уровне - только 2 атомика на операцию
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39554688
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Так он под Windows 8
Лучше тогда уж вручную брейкпоинт на память делатьи в каком потоке он вызовется?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39555407
_StarikPro_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SOFT FOR YOU,
....
Если говорить в теории, то ценность моего решения заключается в нескольких пунктах.
Во-первых, нет явного ограничения на количество элементов в очереди (а в кольцевом есть)
Во-вторых, нет ограничения на количество читающих или пишущих потоков
В-третьих, производительность по идее (если речь не о первом элементе в очереди) на высоком уровне - только 2 атомика на операцию

В моей реализации отсутствуют указанные ограничения если условиться об использовании одной очереди на "один канал передачи данных в одно направление", а про в-третьих вообще молчу... хотя на производительность не тестировал, всё устраивает на текущем этапе...

Пока вижу только одно достоинство, и то сомнительное - простота в применении...

kealon(Ruslan) ,
ситуация: 1 читающий, много пишущих - не самая распространённая

Я это привёл в качестве примера, для доходчивости, так сказать, варианты можно реализовать любые...
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39555409
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_StarikPro_,

Посмотри, где в моем коде ошибка?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39555421
_StarikPro_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SOFT FOR YOU...(если речь не о первом элементе в очереди)...
И опять же, не понимаю, к чему эти условности... первый не первый элемент, в чём проблема закольцевать очередь - тогда все элементы становятся равными
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39555465
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_StarikPro_,

Я пока вижу, что ты языком чешешь
Кольцевой-некольцевой

Ни реализации твоей, ни ответа на вопрос, озвученный в топике
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39555797
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребят, я попробовал заменить Fill на AtomicExchange
Ошибка пока не воспроизводится
Посмотрите у себя пожалуйста https://bitbucket.org/d-mozulyov/lockfree/src
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39555925
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

TestUG падает
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39555941
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Да еклмн
Где там ошибка?!
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556091
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Да еклмн
Где там ошибка?!
не внемлишь же, уже говорил про эту ошибку


вот тебе зависание:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
var
  CCCC: Integer;
function TSyncQueue<T>.Enqueue(const Value: T): Boolean;
var
  Node: PNode;
  Tail: TSyncPointer;
  test: Boolean;
  x: T;
begin
  test := InterlockedIncrement(CCCC) = 3;
  // новый узел
  Node := TSyncAllocator<Pointer,TNothing,T>.New;
  Node.Value := Value;
  Node.Next := nil;

  // подмен€ем FTail на узел
  Tail := FTail.AtomicExchange(Node);
  (*repeat
    Tail := FTail.Copy;
  until (FTail.AtomicCmpExchange(Node, Tail)); *)
  // инициализируем Next предущего узла или сам FHead
  if (Tail.Empty) then
  begin
    if test then begin
      Enqueue(Value);
      Dequeue(x);
    end;
    //FHead.Fill(Node);
    FHead.AtomicExchange(Node);
  end else
  begin
    PNode(Tail.Value).Next := Node;
  end;

  Result := True;
end;

...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556118
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хотя нет вру, ожидание срабатывает

непонятно как без ожидания проверить
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556426
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

В Dequeue же просто вхолостую работает цикл, если Next не инициализирован
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556440
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,
да заметил, 20968902

TestUG падает раз из 5-7 запусков, причём так же как и раньше - два потока для этого достаточно
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556470
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

А идеи, как оно происходит - появились?

Вообще, когда Enqueue есть, а Dequeue нет - это чистой воды потеря элемента. Мои тесты тоже иногда показывают, что теряют элемент.
Уж не ABA ли?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556484
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добавил автотест, получил вот такую картину:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Iteration 1... done
Iteration 2... done
Iteration 3... done
Iteration 4... done
Iteration 5... done
Iteration 6... done
Iteration 7... done
Iteration 8... done
Iteration 9... done
Iteration 10... done
Iteration 11...
Элемент 5448036 потерян
Элемент 5448037 потерян
Элемент 5448038 потерян
Элемент 5448039 потерян


Press Enter to quit

Т.е. потеряно сразу 4 элемента, идущих подряд. Точно ABA. Только где?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556565
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUТ.е. потеряно сразу 4 элемента, идущих подряд. Точно ABA. Только где?
не обязательно, проверь без переиспользования памяти, это исключит АБА
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556579
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Как это - без переиспользования памяти?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556589
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Как это - без переиспользования памяти?выделяешь большой блок и от него отщипываешь пока не закончится

н-р на 100 млн элементов, твоей очереди на 10 секунд точно хватит
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39556628
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Можно в Dequeue нод не возвращать системе
Если комп под рукой - посмотри, пожалуйста
Я только к вечеру до компа дойду
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39557014
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUkealon(Ruslan),

Можно в Dequeue нод не возвращать системе
Если комп под рукой - посмотри, пожалуйста
Я только к вечеру до компа дойду
за 10 раз TestUG не повторился, скорее всего ABA выходит

PS: около 10-11 млн/c держится - "менеджер памяти ноды" надо менять
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39557103
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

В коде есть возможность «эмулировать» очередь через стек
И в стеке используется та же модель аллоцирования памяти. А именно free list - самый элементарный и быстродейственный вариант

И стек не давал ошибок, не давал ABA. Следовательно, дело не в менеджменте памяти, а в самом алгоритме
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39557115
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

про менеджер был вывод, что он довольно медленный

АБА конечно в алгоритме
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39557152
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Да быстрее вроде некуда. Стек и память никуда не удаляется
А как «долгость» может инициировать ABA?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39557168
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

это так, на заметку, с АБА это не связано
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39567487
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

небольшими оптимизациями удалось приблизиться к техническому пределу на 4-х потоках
https://sourceforge.net/p/cl4fpc/code/HEAD/tree/Containers/lfqueues.pas


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
  1 threads
Cicle count: 20324
Cicle count: 21207
Cicle count: 21943
Cicle count: 21369
Cicle count: 21195
Cicle count: 21202
  2 threads
Cicle count: 16711
Cicle count: 16556
Cicle count: 16906
Cicle count: 15959
Cicle count: 16327
Cicle count: 16101
  3 threads
Cicle count: 12555
Cicle count: 13022
Cicle count: 12897
Cicle count: 12576
Cicle count: 13717
Cicle count: 12582
  4 threads
Cicle count: 10971
Cicle count: 10340
Cicle count: 8797
Cicle count: 9477
Cicle count: 10483
Cicle count: 9759

хз тока зачем это надо если критическая секция даст тоже самое.
По идее дальше вся проблема в функции разгрузки
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39567515
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)хз тока зачем это надо если критическая секция даст тоже самоеlf-контейнеры (кроме прочих их достоинств и преимуществ) могут оказаться нужны когда контейнеров надо ахулиард и может оказаться нежелательным задействовать такую массу объектов синхронизации
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39567530
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vavankealon(Ruslan)хз тока зачем это надо если критическая секция даст тоже самоеlf-контейнеры (кроме прочих их достоинств и преимуществ) могут оказаться нужны когда контейнеров надо ахулиард и может оказаться нежелательным задействовать такую массу объектов синхронизациитут така вещь, что все эти оптимизации уже есть в критической секции и реальных обектов синхронизации не так много создаётся. Фактически, в большинстве случаев срабатывает обычный спин-лок.

хотя как вариант возможно неплохое применение на обшаренной между процессами памяти
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39567553
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)все эти оптимизации уже есть в критической секциикрит. секция при всех ее прелестях вещь весьма виндовая а lf без мутексов и т.п. бывают кросс-платформенные
kealon(Ruslan)реальных обектов синхронизации не так много создаётсяно создаться таки могут, а уж "если неприятность может случиться то она непременно случится" (С)
kealon(Ruslan)Фактически, в большинстве случаев срабатывает обычный спин-локну пока contention/starvation не случатся вообще конкурентов у cs практически нет
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39568139
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

А моя очередь разве не быстрее крит секции?
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39568145
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот это никто не смотрел?
http://www.thedelphigeek.com/2010/02/dynamic-lock-free-queue-doing-it-right.html

Ну это я так, на правах мимокрокодила :)
...
Рейтинг: 0 / 0
Lock-free: Доведём очередь до ума
    #39568160
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

Смотрели, но не осилили
Можешь ради интереса поставить его код в какой-нибудь тест
Можно вообще сравнительный тест замутить
...
Рейтинг: 0 / 0
147 сообщений из 147, показаны все 6 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Lock-free: Доведём очередь до ума
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]