c++ - reducción de omp en el vector de cv:: Mat o cv:: Mat en general
opencv parallel-processing (1)
Los tipos como cv::Mat1f
, que usan referencias en lugar de copiar, son realmente peligrosos en este contexto. Usted hace una solución clara y explícita al dividir la región parallel
y el ciclo for
.
#pragma omp declare reduction(vec_mat1f_plus : std::vector<cv::Mat1f> : /
std::transform(omp_out.begin(), omp_out.end(), omp_in.begin(), omp_out.begin(), std::plus<cv::Mat1f>()));
// initializer not necessary if you initialize explicitly
std::vector<cv::Mat1f> mat;
#pragma omp parallel reduction(vec_mat1f_plus : mat)
{
mat = std::vector<cv::Mat1f>(5);
for (auto& elem : mat) {
elem = cv:Mat1f::zeros(1, n);
}
#pragma omp for
for(size_t i=0; i<m; i++){
mat[indexes[m]] += 1;
}
}
No he probado si std::plus<cv::Mat1f>
funciona, pero se ve bien .
Su enfoque con vectMat
también funcionará si proporciona un operator=
que copia profundamente el Mat
subyacente con clone()
y conserva el inicializador.
//In other words, this equilavent to cv::Mat1f mat(5,n)
//i.e. a matrix 5xn
std::vector<cv::Mat1f> mat(5,cv::Mat1f::zeros(1,n));
std::vector<float> indexes(m);
// fill indexes
// m >> nThreads (from hundreds to thousands)
for(size_t i=0; i<m; i++){
mat[indexes[m]] += 1;
}
El resultado esperado es aumentar cada elemento de cada fila en uno. Este es un ejemplo de juguete, la suma real es mucho más compatible. Traté de paralelizarlo con:
#pragma omp declare reduction(vec_float_plus : std::vector<cv::Mat1f> : /
std::transform(omp_out.begin(), omp_out.end(), omp_in.begin(), omp_out.begin(), std::plus<cv::Mat1f>())) /
initializer(omp_priv=omp_orig);
#pragma omp parallel for reduction(vec_float_plus : mat)
for(size_t i=0; i<m; i++){
mat[indexes[m]] += 1;
}
Pero esto falla porque cada elemento de cada fila está inizitializado aleatoriamente. ¿Como puedo resolver esto?
Entonces descubrí que el problema está relacionado con esto . Entonces debería inicializar mat
con:
std::vector<cv::Mat1f> mat(5);
for(size_t i=0; i<mat.size(); i++)
mat[i] = cv::Mat1f::zeros(1,n);
Pero esto crearía problemas con omp_priv = omp_orig
, ya que consideraría std::vector<cv::Mat1f> mat(5);
y sus valores no están definidos. ¿Como puedo resolver esto? La única solución que me vino a la mente es crear una estructura de contenedor, algo así como:
class vectMat{
public:
vectMat(size_t rows, size_t j){
for(size_t i=0; i<rows; i++)
mats.push_back(cv::Mat1f::zeros(1,j));
}
private:
std::vector<cv::Mat1f> mats;
};
Pero entonces, ¿qué debería implementar para que funcione con el resto del código?