У меня есть следующий фрагмент кода 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 раз медленнее?
- Есть ли способ заставить "медленные данные" работать быстрее или любая оптимизация (например, векторизация вычислений) будет одинаково влиять на оба массива (т. Е. "Медленные данные" будут работать медленнее, чем данные ")
EDIT
Полный код здесь: https://gist.github.com/1676742, командная строка для компиляции находится в комментарии в test.cpp
.
Файлы данных находятся здесь: