Могу ли я загрузить значение в регистр без остановки, пока оно не будет извлечено из памяти? - PullRequest
0 голосов
/ 07 ноября 2018

Я хотел бы начать доступ к основной памяти, но пока я получаю новое значение в какой-то момент, я не слишком суетлив относительно того, когда именно новое значение прибывает. А пока я хотел бы продолжить использовать значение, которое в данный момент находится в регистре, а не останавливаться до тех пор, пока загрузка памяти не завершится.

Вот пример мотивирующей игрушки на C. У меня есть рабочий цикл, который постоянно выполняет некоторую работу и накапливает результаты в некотором хранилище. Время от времени я хотел бы поменять местами, где накапливаются значения (аналогично ротации журналов на сервере Linux). Пока каждое вычисленное значение накапливается в одном месте хранения, я счастлив.

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

Как я могу сделать это понятным компилятору / процессору? Это нормально, если для этого требуется непосредственно писать сборку. Мне интересны ответы, которые работают на любой / всех архитектурах.

// does unspecified work and returns an int.
inline int do_work();

// where our main thread accumulates its work
int * accumulator;

// assume that some other thread is concurrently updating this.
// Every so often, we want to switch our accumulator to be a
// newer value taken from here, but we're not fussy about exactly
// when that switch happens.
int * volatile * current_accumulator;


void work_loop() {
    int * accumulator = *current_accumulator;
    // Here, I want to block once until `*current_accumulator`
    // is loaded into a register.
    while (1) {
        for (int i = 0; i < 100; ++i) {
            // This has a dependency on the memory load, and so
            // it will stall until the new value is loaded into
            // the register. However I don't want that. I want the
            // register to update eventually, but I want to always
            // be using the value that happens to currently be there.
            *accumulator += do_work();
        }
        accumulator = *current_accumulator;
    }
}
...