Внеочередное выполнение в ЦП означает, что ЦП может переупорядочивать инструкции для повышения производительности, и это означает, что ЦПУ приходится вести очень изящную бухгалтерию и тому подобное. Есть и другие процессорные подходы, такие как гиперпоточность.
Некоторые причудливые компиляторы понимают (не) взаимосвязанность команд в ограниченной степени и автоматически чередуют потоки команд (возможно, через более длинное окно, чем видит процессор), чтобы лучше использовать процессор. Умышленное чередование во время компиляции плавающих и целочисленных инструкций является еще одним примером этого.
Теперь у меня очень параллельное задание. И у меня обычно есть устаревший одноядерный процессор x86 без гиперпоточности.
Есть ли прямой способ получить тело моего цикла for для чередования этой высокопараллельной задачи, чтобы две (или более) итерации выполнялись вместе? (Это немного отличается от «разматывания петли», насколько я понимаю.)
Моя задача - «виртуальная машина», выполняющая набор инструкций, которые я действительно упростил для иллюстрации:
void run(int num) {
for(int n=0; n<num; n++) {
vm_t data(n);
for(int i=0; i<data.len(); i++) {
data.insn(i).parse();
data.insn(i).eval();
}
}
}
Так что след выполнения может выглядеть так:
data(1) insn(0) parse
data(1) insn(0) eval
data(1) insn(1) parse
...
data(2) insn(1) eval
data(2) insn(2) parse
data(2) insn(2) eval
Теперь я хотел бы иметь возможность делать две (или более) итерации явно параллельно:
data(1) insn(0) parse
data(2) insn(0) parse \ processor can do OOO as these two flow in
data(1) insn(0) eval /
data(2) insn(0) eval \ OOO opportunity here too
data(1) insn(1) parse /
data(2) insn(1) parse
Из профилирования я знаю (например, с помощью Callgrind с параметром --simulate-cache = yes), что синтаксический анализ связан со случайным доступом к памяти (отсутствует кэш), а eval - с выполнением операций в регистрах и последующей записью результатов. Каждый шаг состоит из нескольких тысяч инструкций. Так что, если я смогу смешать два шага для двух итераций одновременно, то процессор, мы надеемся, будет что-то делать, пока происходят пропуски кэша шага разбора ...
Есть ли какое-то безумие в шаблонах c ++ для генерации такого явного параллелизма?
Конечно, я могу выполнять чередование - и даже ошеломление - самостоятельно в коде, но это делает код менее читабельным. И если я действительно хочу нечитабельно, я могу пойти так далеко, как ассемблер! Но наверняка есть какой-то шаблон для такого рода вещей?