2012-02-27 3 views
1

В приведенном ниже коде вычисляется матрица корреляции с учетом ковариационной матрицы. Как я могу написать это лучше? Вопрос этот раздел кода будет работать 1000s раз на матрицах, размеры которых примерно 100 х 100.Оптимизация расчета корреляционной матрицы

// Copy upper triangle of covariance matrix to correlation matrix 
for(i = 0; i < rows; i++){ 
    for(j = i; j < rows; j++){ 
    corrmatrix.array[i * rows + j] = covmatrix.array[i * rows + j]; 
    } 
} 

// Calculate upper triangle of corr matrix 
for(i = 0; i < rows; i++){ 

    root = sqrt(covmatrix.array[(i * rows) + i]);  

    for(j = 0; j <= i; j++){ // Move down 
    corrmatrix.array[ j * rows + i ] /= root; 
    } 

    k = i * rows; 

    for(j = i; j < rows; j++){ // Move across 
    corrmatrix.array[ k + j ] /= root; 
    } 

} 

// Copy upper triangle to lower triangle 
for(i = 0; i < rows; i++){ 
    k = i * rows; 
    for(j = i; j < rows; j++){ 
    corrmatrix.array[ (j * rows) + i ] = corrmatrix.array[ k + j ]; 
    } 
} 

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

PS:

  1. матрицы хранятся в строке-мажор, плотный формат
  2. Я не использую уплотненного хранения в настоящее время.

Спасибо

ответ

1

Первое, что выскакивает у меня есть, что вы делаете разделение по тому же номеру в ваших внутренних петлях.

Не делайте этого. Отдел медленно.

Что вы должны сделать вместо этого следует умножить на обратную root вместо деления на него несколько раз:

inv_root = 1./sqrt(covmatrix.array[(i * rows) + i]); 

for(j = 0; j <= i; j++){ // Move down 
    corrmatrix.array[ j * rows + i ] *= inv_root; 
} 

k = i * rows; 

for(j = i; j < rows; j++){ // Move across 
    corrmatrix.array[ k + j ] *= inv_root; 
} 

Хотя эта оптимизация может показаться очевидным для компилятора, это не может быть позволено сделать эту оптимизацию из-за строгости плавающей запятой. Вы можете попробовать настроить параметры с плавающей запятой с помощью -ffast-math (в GCC) или что-то подобное.

+0

Спасибо, добавлю, что изменение. Есть ли еще какие-то оптимизации, которые я могу сделать? – mod0

+0

Нет, что легко. В зависимости от вашего компилятора он может его векторизовать для вас. Помимо этого, код, вероятно, будет связан огромным количеством доступа к памяти, которое вы делаете. Единственный способ исправить это - реструктурировать алгоритм, который может быть или не быть легким. – Mysticial

+0

Хорошо. Спасибо. – mod0