Аппаратная транзакционная память: _xbegin() возвращает 0C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Гость
 Аппаратная транзакционная память: _xbegin() возвращает 0

Сообщение Гость »


Согласно документации gcc: x86-transactional-memory-intrinsics.html, в случае сбоя/прерывания транзакции _xbegin() должен возвращать статус прерывания . Однако я иногда обнаруживаю, что он возвращает 0. И частота очень высокая. В какой ситуации **_xbegin()** вернет 0?

Проверив руководство, я обнаружил, что многие ситуации могут привести к такому результату. Например, CPUID, SYSTEMCALL, CFLUSH.etc. Однако я не думаю, что мой код вызвал какой-либо из них.

Вот мой код: Имитируя небольшой банк, случайный перевод 1 доллара на другой счет.

#include "immintrin.h" #include #include #include использование пространства имен std; #define n_threads 1 #define OPSIZE 1000000000 typedef структура Account{ длинный баланс; длинный номер; } __attribute__((aligned(64))) account_t; typedef struct Bank{ account_t* аккаунты; длинный размер; } Bank_t; логическое завершение = 0; long *tx, *_abort, *capacity, *debug, *failed, *conflict, *zero; void* f1(bank_t* банк, int id){ for(int i=0; isize; int dst = rand()%bank->size; в то время как (источник == dst) { dst = rand()%bank->size; } пока (правда) { беззнаковый стат = _xbegin(); если(стат == _XBEGIN_STARTED){ банк->счета[источник].баланс++; банк->счета[dst].баланс--; _xend(); asm Летучий("":::"Память"); tx[id]++; перерыв; }еще{ _abort[id]++; если (стат == 0){ ноль[id]++; } если (стат & _XABORT_CONFLICT){ конфликт[id]++; } если (стат & _XABORT_CAPACITY){ емкость[id]++; } если (стат & _XABORT_DEBUG){ отладка[id]++; } если ((stat & _XABORT_RETRY) == 0){ не удалось[id]++; перерыв; } если (стат & _XABORT_NESTED){ printf("[ PANIC ] _XABORT_NESTED\n"); выход (-1); } если (стат & _XABORT_EXPLICIT){ printf("[ паника ] _XBEGIN_EXPLICIT\n"); выход (-1); } } } } вернуть НУЛЬ; } void* f2(bank_t* банк){ printf("_heartbeat function\n"); длинный Last_txs = 0, Last_aborts = 0, Last_Capacities = 0, Last_debugs = 0, Last_faileds = 0, Last_Conflicts = 0, Last_zeros = 0; длинный txs=0, прерывания=0, мощности=0, отладки=0, сбои=0, конфликты=0, нули = 0; пока(1){ Last_txs = ТКС; Last_aborts = прерывание; Last_capacities = мощности; Last_debugs = отладки; Last_conflicts = конфликты; Last_faileds = не удалось; Last_zeros = нули; txs=aborts=capacities=debugs=faileds=conflicts=zeros = 0; for(int i=0; iсчета = новый account_t[счета]; банк->размер = счета; for(int i=0; iсчета.number = я; банк->счета.баланс = 0; } поток* pid[n_threads]; tx = новый длинный [n_threads]; _abort = новый длинный [n_threads]; емкость = новый длинный [n_threads]; отладка = новый длинный [n_threads]; не удалось = новый длинный [n_threads]; конфликт = новый длинный [n_threads]; ноль = новый длинный [n_threads]; поток* _heartbeat = новый поток (f2, банк); for(int i=0; iсчета[0], банка->счета1. 0xf41080,0xf410c0。 [*]Использование -O0 и asm Летучая(""::"memory");поэтому проблем с переупорядочением инструкций не возникает. [*]
Частота прерываний увеличивается со временем. Вот результат

txs 84 прерывание 0 сбоев 0 возможностей 0 отладок 0 конфликтов 0 ноль 0 txs 17070804 прерывание 71 сбой 68 пропускная способность 9 отладок 0 конфликт 3 ноль 59 txs 58838 прерывание 9516662 сбой 9516661 пропускная способность 0 отладки 0 конфликт 1 ноль 9516661 txs 0 прерываний 9550428 сбоев 9550428 возможностей 0 отладок 0 конфликтов 0 нуля 9550428 txs 0 прерываний 9549254 сбоев 9549254 возможностей 0 отладок 0 конфликтов 0 нуля 9549254 [*]Даже если n_threads равно 1, результат тот же.
[*]
Если я добавлю грубую блокировку после отката, как показано ниже, результат будет правильным.
int Fallback_lock; логическое значение rtm_begin (целевой идентификатор) { в то время как (истина) { беззнаковый стат; стат = _xbegin (); если (стат == _XBEGIN_STARTED) { вернуть истину; } еще { _abort[id]++; если (стат == 0){ ноль[id]++; } //вызов какой-нибудь резервной функции если (стат& _XABORT_CONFLICT){ конфликт[id]++; } // повторная попытка не удастся if ((stat & _XABORT_RETRY) == 0) { не удалось[id]++; //захватываем резервную блокировку while (!__sync_bool_compare_and_swap(&fallback_lock,0,1)) { } вернуть ложь; } } } } .... in_rtm = rtm_begin (идентификатор); y = резервная_блокировка; счета[источник].баланс--; счета[dst].баланс++; если (in_rtm){ _xend(); }еще{ while(!__sync_bool_compare_and_swap(&fallback_lock, 1, 0)){ } }
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»