I need help

General OpenMP discussion

I need help

Postby sylar_br » Mon Aug 19, 2013 11:28 am

I am a beginner in openMP and I would like to know if someone here could check this fragment of code in c++ and tell me if I am using it correctly... any hint would be helpful...
Code: Select all
int main(int argc, char* argv[]){
   if(argc<=1) return 0;
   if(argv == NULL) return 0;

   Parameters parameters;

   list<Result> result_list;

   #pragma omp parallel default(shared)
   {

    #pragma omp single nowait
    {
        if(!read_parameters(argc, argv, parameters))
        {
            cout<<"Wrong number of parameters or invalid parameters..."<<endl;
            cout<<"The program must be called with the following parameters:"<<endl;
            cout<<"\t- num_threads: The number of threads"<<endl;
            cout<<"\t- max_scale: The maximum scale that can be applied to the templates in the main image"<<endl;
            cout<<"\t- main_image: The main image path"<<endl;
            cout<<"\t- t1 ... tn: The list of the template paths. Each template separated by a space"<<endl;
            cout<<endl<<"For example : ./run 4 3 img.bmp template1.bmp template2.bmp"<<endl;
            return -1;
        }
    }

   //Read the main image
   #pragma omp master
   Accelerate::Image main_image = Accelerate::Image::create_image_from_bitmap(parameters.main_image_name);
   //iterates over the pattern images

   for(string temp_name : parameters.template_names)
    {
      //Read a specific pattern image
      #pragma omp master
      Accelerate::Image template_image = Accelerate::Image::create_image_from_bitmap(temp_name);
      //Then retrieve the ID of the image (the 3 first characters
      int template_id = atoi(temp_name.substr(0, 3).c_str());
      //Iterate over some possible scales (you can add more steps and you can also check rotations)
      //The sample is really simple because you have to create a good algorithm able to match
      //a pattern in an image

      #pragma omp for private(s,wm, hm) schedule(runtime)
      for(unsigned int s=1; s<=parameters.max_scale; s++)
        {
            //Create a scaled image
            #pragma omp master
            Accelerate::Image temp = template_image.scale_image(s);
            //iterates on the main image pixels
            for(unsigned int wm=0; wm<main_image.get_width(); wm++)
            {
                for(unsigned int hm=0; hm<main_image.get_height(); hm++)
                {
                    //Try to match the template

                        #pragma omp single nowait
                        {
                            if(match_template(main_image, temp, hm, wm))
                            {
                                //The pattern image has been found so save the result
                                Result result;
                                result.pattern_ID = template_id;
                                result.position_x = wm;
                                result.position_y = hm;
                                result_list.push_back(result);
                            }
                        }
                }
            }
        }
    }

   //sort the result list
   result_list.sort(compare_results);

   //Print the results
   for(Result res : result_list){
      cout<<res.pattern_ID<<"\t"<<res.position_x<<"\t"<<res.position_y<<endl;
   }
    return 0;
    }
}
sylar_br
 
Posts: 2
Joined: Mon Aug 19, 2013 11:05 am

Re: I need help

Postby MarkB » Tue Aug 20, 2013 2:57 am

Hi there,

It looks like you are bit confused about what the single and master constructs do. They both mean that only one thread executes the block of code while the others skip over it, and they cannot be nested inside a worksharing for construct.

I am assuming the parallelism you are trying to exploit is that calls to match_template are independent for different values of s. If so, I would start with using a simple parallel for construct and do all the I/O on the master thread like this:

Code: Select all
    int main(int argc, char* argv[]){
       if(argc<=1) return 0;
       if(argv == NULL) return 0;

       Parameters parameters;

       list<Result> result_list;




            if(!read_parameters(argc, argv, parameters))
            {
                cout<<"Wrong number of parameters or invalid parameters..."<<endl;
                cout<<"The program must be called with the following parameters:"<<endl;
                cout<<"\t- num_threads: The number of threads"<<endl;
                cout<<"\t- max_scale: The maximum scale that can be applied to the templates in the main image"<<endl;
                cout<<"\t- main_image: The main image path"<<endl;
                cout<<"\t- t1 ... tn: The list of the template paths. Each template separated by a space"<<endl;
                cout<<endl<<"For example : ./run 4 3 img.bmp template1.bmp template2.bmp"<<endl;
                return -1;
            }


       //Read the main image

       Accelerate::Image main_image = Accelerate::Image::create_image_from_bitmap(parameters.main_image_name);
       //iterates over the pattern images

       for(string temp_name : parameters.template_names)
        {
          //Read a specific pattern image

          Accelerate::Image template_image = Accelerate::Image::create_image_from_bitmap(temp_name);
          //Then retrieve the ID of the image (the 3 first characters
          int template_id = atoi(temp_name.substr(0, 3).c_str());
          //Iterate over some possible scales (you can add more steps and you can also check rotations)
          //The sample is really simple because you have to create a good algorithm able to match
          //a pattern in an image

          #pragma omp parallel for  default(none) shared(main_image, result_list, parameters, template_image, template_id) schedule(runtime)
          for(unsigned int s=1; s<=parameters.max_scale; s++)
            {
                //Create a scaled image

                Accelerate::Image temp = template_image.scale_image(s); // each thread has it's own private copy of temp
                //iterates on the main image pixels
                for(unsigned int wm=0; wm<main_image.get_width(); wm++)
                {
                    for(unsigned int hm=0; hm<main_image.get_height(); hm++)
                    {
                        //Try to match the template


                                if(match_template(main_image, temp, hm, wm))
                                {
                                    //The pattern image has been found so save the result
                                    Result result;
                                    result.pattern_ID = template_id;
                                    result.position_x = wm;
                                    result.position_y = hm;
                           #pragma omp critical
                                    {
                                    result_list.push_back(result);
                                    }
                                }

                    }
                }
            }
       

       //sort the result list
       result_list.sort(compare_results);

       //Print the results
       for(Result res : result_list){
          cout<<res.pattern_ID<<"\t"<<res.position_x<<"\t"<<res.position_y<<endl;
       }
        return 0;
        }
    }


I may have some mismatched braces in there, but I hope you get the idea.

The critical section is needed to prevent multiple threads trying to update the result_list at the same time. This should work OK provided results are not found very frequently, in which case it may become a bottleneck. If this is the case, then it might be better to give each thread its own result_list, and merge them together at the end.


Hope that helps,
Mark.
MarkB
 
Posts: 432
Joined: Thu Jan 08, 2009 10:12 am

Re: I need help

Postby sylar_br » Tue Aug 20, 2013 2:44 pm

thanks a lot Mark... your suggetions were very helpful... I was almost giving up.. now I'm understanding OpenMP... the function below is "match_template"... can I use openMP to rewrite it or it´s not necessary?
Code: Select all
bool match_template(const Accelerate::Image& main_image, const Accelerate::Image& template_image, unsigned int h, unsigned int w){
   //The next cases are not possible
   if(main_image.get_width() - w < template_image.get_width()) return false;
   if(main_image.get_height() - h < template_image.get_height()) return false;
   //Iterates over the pattern and compare each pixel with the pixels of the main image
   for(unsigned int wt=0; wt<template_image.get_width(); wt++){
      for(unsigned int ht=0; ht<template_image.get_height(); ht++){
         //If a single pixel do not match, we return false
         //You can also improve this part of the algorithm as some images can have different contrasts,
         //lights, etc
         if(template_image.get_pixel(ht, wt).r != main_image.get_pixel(h+(ht), w+(wt)).r ||
            template_image.get_pixel(ht, wt).g != main_image.get_pixel(h+(ht), w+(wt)).g ||
            template_image.get_pixel(ht, wt).b != main_image.get_pixel(h+(ht), w+(wt)).b){
            return false;
         }
      }
   }
   return true;
}




sylar_br
 
Posts: 2
Joined: Mon Aug 19, 2013 11:05 am

Re: I need help

Postby MarkB » Wed Aug 21, 2013 2:39 am

You don't need to rewrite this function. It doesn't modify any shared variables, and variables declared inside it are automatically private to each thread.
MarkB
 
Posts: 432
Joined: Thu Jan 08, 2009 10:12 am


Return to Using OpenMP

Who is online

Users browsing this forum: Google [Bot], Yahoo [Bot] and 4 guests