Развертывание цикла и его влияние на конвейерную обработку и CPE (есть решение, но я его не понимаю)

Под строкой находится вопрос по практическому тесту. На самом деле в таблице есть все решения. Однако мне нужно пояснить, почему решения такие, какие они есть. (Читайте вопрос под горизонтальной чертой).

Например, очень хотелось бы понять ряд решения для A2 и A3.

Насколько я вижу, у вас в A2 происходит следующая ситуация:

  1. x * y
  2. xy * r
  3. иксир * г

Теперь давайте посмотрим, как это будет в конвейере:

|1|2|3|4|5|6|7|8 |9|10|11|12|13|14|15|16|17|18|19|20|21|
| | | | | | | |  | |  |  |  |  |  |  |  |  |  |  |  |  |
{ x * y } | | |  | |  |  |  |  |  |  |  |  |  |  |  |  |
        { xy * r } |  |  |  |  |  |  |  |  |  |  |  |  |
                 { xyr * z  }  |  |  |  |  |  |  |  |  |
//next iteration, which means different x, y and z's|  |
                   {x2 * y2    }  |  |  |  |  |  |  |  |
                               {x2y2 * r   } // this is dependent on both previous r and x2y2
                                           {x2y2r * z  }

Таким образом, мы можем перекрывать xyr * z и x2 * y2, потому что нет конфликтов зависимостей. Однако это только избавление от 3 циклов, верно?

Таким образом, все равно будет (12 - 3) / 3 = 9 / 3 = 3 цикла на элемент (три элемента). Как же они получают 8/3 CPE для A2?

Любая помощь в понимании этой концепции будет принята с благодарностью! Торопиться особо некуда, так как тест только на следующей неделе. Если есть какая-либо другая информация, которая вам нужна, пожалуйста, дайте мне знать!


(Ниже приведен полный текст тестового вопроса, а также таблица, полностью заполненная решениями)

Рассмотрим следующую функцию для вычисления произведения массива из n целых чисел.

Мы развернули цикл в 3 раза.

int prod(int a[], int n) {

int i, x, y, z;
int r = 1;

for(i = 0; i < n-2; i += 3) {
    x = a[i]; y = a[i+1]; z = a[i+2];
    r = r * x * y * z; // Product computation
}
for (; i < n; i++)
    r *= a[i];

return r;
}

Для строки, помеченной как вычисление продукта, мы можем использовать круглые скобки для создания пяти различных ассоциаций вычисления следующим образом:

r = ((r * x) * y) * z; // A1
r = (r * (x * y)) * z; // A2
r = r * ((x * y) * z); // A3
r = r * (x * (y * z)); // A4
r = (r * x) * (y * z); // A5

Мы выражаем производительность функции через количество циклов на элемент (CPE). Как описано в книге, эта мера предполагает, что время выполнения, измеряемое в тактовых циклах, для массива длины n является функцией вида Cn + K, где C — CPE.

Мы измерили пять версий функции на Intel Pentium III. Напомним, что операция целочисленного умножения на этой машине имеет задержку 4 цикла и время выдачи 1 цикл.

В следующей таблице показаны некоторые значения CPE, а другие значения отсутствуют. Измеренные значения CPE - это те, которые действительно наблюдались. «Теоретическое CPE» означает производительность, которая была бы достигнута, если бы единственным ограничивающим фактором были задержка и время выдачи целочисленного множителя.

введите здесь описание изображения

Заполните пропущенные записи. Для отсутствующих значений измеренного CPE вы можете использовать значения из других версий, которые будут иметь такое же вычислительное поведение. Для значений теоретического CPE можно определить количество циклов, которое потребуется для итерации, учитывая только задержку и время выдачи множителя, а затем разделить на 3.


person Kyra Westwood    schedule 05.11.2012    source источник
comment
В чем вопрос??? Оптимизация цикла лучше всего выполняется оптимизирующим компилятором. С недавним GCC попробуйте скомпилировать с gcc -Wall -O3 -mtune=native -march=native; оптимизирующие компиляторы обычно лучше, чем программисты-люди для этих вещей....   -  person Basile Starynkevitch    schedule 05.11.2012
comment
Вопрос в том, как они получают 8/3 CPE на A2? Почему не 9/3? (Я выделил это жирным шрифтом, чтобы помочь вам найти его :)). Я согласен с тем, что последние компиляторы делают такие возни устаревшими. Поверьте мне, я бы предпочел изучать концепции программирования более высокого уровня. К сожалению, мой университет считает необходимым, чтобы каждый специалист по CS изучал такие запутанные тонкости оптимизации. Я бы предпочел играть с такими высокоуровневыми вещами, как Ruby on Rails :)   -  person Kyra Westwood    schedule 05.11.2012
comment
Я действительно должен извиниться за то, что мне трудно понять, о чем я спрашиваю. Я просто хотел дать достаточно информации о проблеме. Извините, я мало пользовался этим сайтом!   -  person Kyra Westwood    schedule 05.11.2012
comment
Ваш университет делает это правильно. Я предсказываю, что оптимизирующие компиляторы будут существовать дольше, чем Ruby on Rails.   -  person Simon Richter    schedule 05.11.2012


Ответы (1)


Не зная архитектуры процессора, мы можем только догадываться.

Моя интерпретация заключается в том, что временная диаграмма показывает только часть конвейера, от сбора операндов до записи результата, потому что это то, что имеет отношение к разрешению зависимостей.

Теперь большое если: если между преобразователем зависимостей и исполняющими модулями есть буферный этап, можно было бы начать третье умножение первой группы (3 ) и первое умножение второй группы (4) со смещением 8.

Поскольку 3 зависит от 2, нет смысла использовать здесь другой модуль, поэтому 3 ставится в очередь на модуль 1 сразу после < эм>2. Следующая инструкция 4 не зависит от предыдущего результата, поэтому ее можно поставить в очередь на блок 2 и запустить параллельно.

Теоретически это может произойти уже в цикле 6, что дает CPE 6/3. На практике это зависит от конструкции процессора.

person Simon Richter    schedule 05.11.2012