Умножение с плавающей запятой выполняется медленнее в зависимости от операндов в C

Я выполняю вычисление трафарета для матрицы, которую я ранее считал из файла. Я использую два разных типа матриц (тип NonZero и тип Zero). Оба типа разделяют значение границ (обычно 1000), в то время как остальные элементы равны 0 для нулевого типа и 1.

Код сохраняет матрицу файла в двух распределенных матрицах одинакового размера. Затем он выполняет операцию с каждым элементом одной матрицы, используя свое собственное значение и значения соседей (сложение x 4 и mul x 1), и сохраняет результат во второй матрице. После завершения вычислений указатели на матрицы меняются местами, и одна и та же операция выполняется конечное количество раз. Здесь у вас есть основной код:

#define GET(I,J) rMat[(I)*cols + (J)]
#define PUT(I,J) wMat[(I)*cols + (J)]

for (cur_time=0; cur_time<timeSteps; cur_time++) {
    for (i=1; i<rows-1; i++) {
        for (j=1; j<cols-1; j++) {
            PUT(i,j) = 0.2f*(GET(i-1,j) + GET(i,j-1) + GET(i,j) + GET(i,j+1) + GET(i+1,j));
        }
    }
    // Change pointers for next iteration
    auxP = wMat;
    wMat = rMat;
    rMat = auxP;
}

Случай, который я раскрываю, использует фиксированное количество timeSteps (внешние итерации) и размер матрицы 8192 строки и 8192 столбца, но проблема сохраняется при изменении количества timeSteps или размера матрицы. Обратите внимание, что я измеряю только время этой конкретной части алгоритма, поэтому чтение матрицы из файла и ничего другого не влияет на измерение времени.

Что происходит, так это то, что я получаю разное время в зависимости от того, какой тип матрицы я использую, получение гораздо худшей производительности при использовании типа Zero (любая другая матрица работает так же, как тип NonZero, поскольку я уже пытался сгенерировать матрицу, полную случайных значений).

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

Такое поведение, безусловно, странно для меня, так как я думал, что операции с плавающей запятой были независимо от значений операндов, что здесь не похоже. Я также попытался захватить и показать исключения SIGFPE в случае, если это была проблема, но я не получил результатов.

В случае, если это помогает, я использую процессор Intel Nehalem и gcc 4.4.3.

17
задан Stephen Canon 5 May 2011 в 01:17
поделиться