x86, эквивалентный для LWARX и STWCX

xrange только хранилища параметрические усилители диапазона и генерирует числа по требованию. Однако реализация C Python в настоящее время ограничивает свой args C longs:

xrange(2**32-1, 2**32+1)  # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1)   # OK --> [4294967295L, 4294967296L]

Примечание, что в Python 3.0 существуют [только 112] и он ведет себя как 2.x xrange, но без ограничений на минимальные и максимальные конечные точки.

9
задан Grant Peters 27 July 2009 в 11:23
поделиться

6 ответов

Как упоминал Майкл, вы, вероятно, ищете инструкцию cmpxchg .

Однако важно отметить, что метод PPC для выполнения этого известен как Загрузить ссылку / сохранить условную (LL / SC), тогда как в архитектуре x86 используется Сравнение и замена (CAS). LL / SC имеет более сильную семантику, чем CAS, в том смысле, что любое изменение значения по условному адресу приведет к сбою хранилища, даже если другое изменение заменяет значение тем же значением, на котором была обусловлена ​​загрузка. CAS, с другой стороны, в этом случае преуспеет. Это известно как проблема ABA (дополнительную информацию см. По ссылке CAS).

Если вам нужна более сильная семантика в архитектуре x86, это можно приблизительно определить, используя инструкцию x86s сравнения и замены двойной ширины (DWCAS) cmpxchg8b или cmpxchg16b в x86_64. Это позволяет вам атомарно поменять местами сразу два последовательных слова «естественного размера» вместо одного обычного. Основная идея состоит в том, что одно из двух слов содержит интересующее значение, а другое - постоянно увеличивающееся «количество мутаций». Хотя это технически не устраняет проблему, вероятность циклического перехода счетчика мутаций между попытками настолько мала, что он является разумной заменой для большинства целей.

Основная идея состоит в том, что одно из двух слов содержит интересующее значение, а другое содержит постоянно увеличивающийся «счетчик мутаций». Хотя это технически не устраняет проблему, вероятность циклического перехода счетчика мутаций между попытками настолько мала, что он является разумной заменой для большинства целей.

Основная идея состоит в том, что одно из двух слов содержит интересующее значение, а другое - постоянно увеличивающееся «количество мутаций». Хотя это технически не устраняет проблему, вероятность того, что счетчик мутаций будет циклически повторяться между попытками, настолько мала, что он является разумной заменой для большинства целей.

11
ответ дан 4 December 2019 в 13:04
поделиться

x86 does not directly support "optimistic concurrency" like PPC does -- rather, x86's support for concurrency is based on a "lock prefix", see here. (Some so-called "atomic" instructions such as XCHG actually get their atomicity by intrinsically asserting the LOCK prefix, whether the assembly code programmer has actually coded it or not). It's not exactly "bomb-proof", to put it diplomatically (indeed, it's rather accident-prone, I would say;-).

2
ответ дан 4 December 2019 в 13:04
поделиться

Вы, вероятно, ищете семейство инструкций cmpxchg.

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

Посмотрите здесь для быстрого обзора того, что доступно.

Вы, вероятно, получите что-то похожее на это:

mov ecx,dword ptr [esp+4]
mov edx,dword ptr [esp+8]
mov eax,dword ptr [esp+12]
lock cmpxchg dword ptr [ecx],edx
ret 12

Вы должны прочитать этот документ ...

Изменить

] В ответ на обновленный вопрос, хотите ли вы сделать что-то вроде Boost shared_ptr ? Если да, взгляните на этот код и файлы в этом каталоге - они определенно помогут вам начать работу.

1
ответ дан 4 December 2019 в 13:04
поделиться

То, что вы пытаетесь сделать, не сработает так, как вы ожидаете. То, что вы реализовали выше, можно сделать с помощью функции InterlockedIncrement (функция Win32; сборка: XADD).

Причина, по которой ваш код не выполняет то, что вы думаете, заключается в том, что другой поток все еще может изменить значение между вторым считыванием * ptr и stwcx без аннулирования stwcx.

0
ответ дан 4 December 2019 в 13:04
поделиться

если вы используете 64 бита и ограничиваете себя 1 ТБ кучи, вы можете упаковать счетчик в 24 неиспользуемых верхних бита. если у вас есть указатели, выровненные по словам, также доступны нижние 5 бит.

int* IncrementAndRetrieve(int **ptr)
{
  int val;
  int *unpacked;
  do
  {   
    val = *ptr;
    unpacked = unpack(val);

    if(unpacked == NULL)
      return NULL;
    // pointer is on the bottom
  } while(!cas(unpacked, val, val + 1));
  return unpacked;
}
1
ответ дан 4 December 2019 в 13:04
поделиться

Не знаю, делают ли LWARX и STWCX недействительными всю строку кэша, а CAS и DCAS. Это означает, что, если вы не готовы выбросить много памяти (64 байта на каждый независимый "блокируемый" указатель), вы не увидите значительных улучшений, если вы действительно подвергнете свое программное обеспечение нагрузке. Лучшие результаты, которые я видел до сих пор, были, когда люди сознательно использовали 64b, планировали свои структуры вокруг него (упаковывая вещи, которые не будут предметом споров), сохраняли все выровненные по границам 64b и использовали явные барьеры для чтения и записи данных. Аннулирование строки кэша может стоить примерно от 20 до 100 циклов, что делает его более серьезной проблемой производительности, чем просто предотвращение блокировки.

Кроме того, вам придется спланировать другую стратегию распределения памяти для управления контролируемой утечкой (если вы можете разделить код на логическую «обработку запроса» - один запрос «утекает», а затем в конце освобождает весь объем памяти) или управление распределением с данными, так что одна конкурирующая структура никогда не получает память, используемую элементами той же структуры / коллекции (для предотвращения ABA). Некоторые из них могут быть очень противоречивыми, но либо это, либо расплата за сборку мусора.

1
ответ дан 4 December 2019 в 13:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: