Проблемы с введением SIMD-команд в код - PullRequest
0 голосов
/ 31 июля 2011

У меня есть базовая функция вычисления, которую я применяю к каждому элементу в массиве.Эта функция делает больше, чем просто суммирует два вектора.

Я хотел работать над несколькими элементами из моего массива параллельно, используя команды SIMD.

Поскольку я нашел такие примеры слишком простыми для моего случая(они не включают вызовы функций): http://www.doc.ic.ac.uk/~nloriant/files/scfpsc-pc.pdf

Я попытался использовать обозначение массива, как здесь: http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/cpp/mac/optaps/common/optaps_elem_functions.htm

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

Если кто-то может мне помочь или отослать меняхороший источник для моих нужд, я буду очень благодарен.

Спасибо !!!!


пример кода:

Это базовая функция применяетсядля каждого элемента в массиве:

float VarFlow::gauss_seidel_step(IplImage* u, int i, float h, float J11, float J12, float J13, float vi){

int x = i%u->width;
int y = i/u->width;

int start_y, end_y, start_x, end_x;
int N_num = 0;

start_y = y - 1;
end_y = y + 1;
start_x = x - 1;
end_x = x+1;         

float temp_u = 0;

// Sum top neighbor    
if(start_y > -1){              

    temp_u += *((float*)(u->imageData + start_y*u->widthStep) + x);

    N_num++;

}

// Sum bottom neighbor            
if(end_y < u->height){   

    temp_u += *((float*)(u->imageData + end_y*u->widthStep) + x);

    N_num++;

}

// Sum left neighbor
if(start_x > -1){              

    temp_u += *((float*)(u->imageData + y*u->widthStep) + start_x);

    N_num++;

}

// Sum right neighbor
if(end_x < u->width){              

    temp_u += *((float*)(u->imageData + y*u->widthStep) + end_x);

    N_num++;

}

temp_u = temp_u - (h*h/alpha)*(J12*vi + J13);
temp_u = temp_u / (N_num + (h*h/alpha)*J11);

return temp_u;

}

Я хотел бы объявить его с помощью __declspec (вектор) и назвать его так:

    u_ptr[0:max_i:1] = gauss_seidel_step(imgU, vect[0:max_i:1], h, fxfx_ptr[0:max_i:1], fxfy_ptr[0:max_i:1], fxft_ptr[0:max_i:1], v_ptr[0:max_i:1]);
    v_ptr[0:max_i:1] = gauss_seidel_step(imgV, vect[0:max_i:1], h, fyfy_ptr[0:max_i:1], fxfy_ptr[0:max_i:1], fyft_ptr[0:max_i:1], u_ptr[0:max_i:1]);

Вместо цикла for.

Я буду рад получить направление с этим (возможно, ссылка на аналогичный пример), но не полное решение.

Спасибо!

1 Ответ

3 голосов
/ 13 августа 2011

SIMD и условное ветвление плохо сочетаются.

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

, например

if(end_x < u->width){                  
    temp_u += value;    
    N_num++;    
}

становится

ltmask = (end_x < u->width); // see _mm_cmplt_ps
temp_u += ltmask*value; // see _mm_add_ps, _mm_and_ps
N_num += ltmask; // use _mm_and_ps with a vector of 1.0f
...