Как производительность зависит от значений базовых данных

У меня есть следующий фрагмент кода C ++ (часть C ++ - это класс профилировщика, который здесь опущен), скомпилированный с помощью VS2010 (64-битная машина Intel). Код просто умножает массив чисел с плавающей запятой ( arr2 ) на скаляр и помещает результат в другой массив ( arr1 ):

int M = 150, N = 150;
int niter = 20000; // do many iterations to have a significant run-time
float *arr1 = (float *)calloc (M*N, sizeof(float));
float *arr2 = (float *)calloc (M*N, sizeof(float));

// Read data from file into arr2

float scale = float(6.6e-14);

// START_PROFILING
for (int iter = 0; iter < niter; ++iter) {
    for (int n = 0; n < M*N; ++n) {         
        arr1[n] += scale * arr2[n];
    }
}
// END_PROFILING

free(arr1);
free(arr2); 

Часть чтения из файла и профилирование (т.е. измерение времени выполнения) здесь для простоты опущено.

Когда arr2 инициализируется случайными числами в диапазоне [0 1], код выполняется примерно в 10 раз быстрее по сравнению со случаем, когда arr2 инициализируется разреженным массивом. в котором около 2/3 значений - нули. Я поигрался с параметрами компилятора / fp и / O , которые немного изменили время выполнения, но соотношение 1:10 было примерно сохранено.

  • Почему производительность зависит от фактических значений? Что делает ЦП по-другому, из-за чего разреженные данные работают в ~ 10 раз медленнее?
  • Есть ли способ сделать так, чтобы «медленные данные» выполнялись быстрее, или любая оптимизация (например, векторизация вычислений) будет иметь одинаковый эффект на обоих массивы (т.е. «медленные данные» все равно будут работать медленнее, чем «быстрые данные»)?

ИЗМЕНИТЬ

Полный код находится здесь: https://gist.github.com/1676742 , командная строка для компиляции находится в комментарии в тесте .cpp .

Файлы данных находятся здесь:

8
задан Itamar Katz 25 January 2012 в 15:23
поделиться