Lab 4: OMP Imaging

Objectives

To use multiple threads (cores) to write to an image

Assignment

  1. Use the rgb_t class (in the ray tracer's pixel.* files) to define an image class img_t that contains as its pirvate data members:
    	int                w,h;
    	rgb_t<uchar>       *img;
    	
    Allocate w*h space for the image:
    	img = new rgb_t<uchar>[w*h];
    	
    and initialize it to 0 (black image):
    	memset(img,0,3*w*h);
    	
    in the class constructor.
  2. Using the img_t class to declare img (typically done in main()) use the 2D-to-1D coordinate conversion [y*w + x] to access the 1D array (how the imgloc index was used previously) to set each pixel's color:
    	rgb_t<double>	color;
    	rgb_t<uchar>	icolor;
    
      for(int y=h-1;y>=0;y--) {
        for(int x=0;x<w;x++) {
    
          color = rgb_t<double>(1.0,0.0,1.0); // red
    
          for(int i=0;i<3;i++)
            icolor[i] = static_cast<uchar>(255.0 * color[i]);
    
          img[y*w + x] = icolor;
        }
      }
    	
  3. Following the loop, report the time taken to construct the image, then open an output file std::ofstream ofs and write the image to this file via
      ofs.open("test.ppm");
      ofs << img;
      ofs.close();
    	
    Clearly, you will need to overload the standard template library ostream operator<<() for the img_t class:
    friend std::ostream& operator<<(std::ostream& s, const img_t& rhs);
    	
    This is a wee bit tricky...you need to figure out how to output the three R,G,B pixels using ostream's write() and where this is done.
  4. Compile and run the program and then check your image to see that it looks like what you expect, e.g., all red.
  5. To parallelize the image construction loop:
    1. before the nested image processing loop, find the number of cores available and set the chunk size:
        #pragma omp parallel private(tid)
        {
          if((tid = omp_get_thread_num())==0)
            ncores = omp_get_num_threads();
        }
        chunk = h/ncores;
      		
    2. parallelize the image processing loop with the following #pragma omp directive:
        #pragma omp parallel for \
                  shared(w,h,img) \
                  private(tid,color,icolor) \
                  schedule(static,chunk)
      		
    Finally, inside your image processing loop, manipulate the chunk that each core is working on by setting a different color, e.g., use a switch statement to produce a different color for each tid— you should get an image with as many color bands as there are cores, e.g., on my dual-core laptop I get this image:

Turn in

Turn in all of your code, in one tar.gz archive of your lab##/ directory, including:
  1. A README file containing
    1. Course id--section no
    2. Name
    3. Lab description
    4. Brief solution description (e.g., program design, description of algorithm, etc., however appropriate).
    5. Lessons learned, identified interesting features of your program
    6. Any special usage instructions
  2. Makefile
  3. source code (.h headers and .cpp source)
  4. object code (do a make clean before tar)

How to hand in

See sendlab notes