{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[Link to this document's Jupyter Notebook](./0225-HW2_OMP.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are two due dates for this assignment. First, you need to set up your assignment git repository on or before **_Feburary 4th_** so your instructor can test and make sure everything is working as expected. Second, you then need to complete the assignment instructions and then add/commit/push your files to your git repository on or before **_11:59pm on Thursday February 25_**. Your instructor highly recommends committing early and often. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Homework 2: Image Processing using OMP\n", "\n", "In this assignment, you are going to modify and improve the processing speed of an edge detector for grayscale PNG images. Edge detection is an image processing technique to find boundaries of objects in images. Here are an example image and the detected edges:\n", "\n", "**Note:** this homework was motivated and adapted from: https://web.stanford.edu/class/cs315b/assignment1.html\n", "\n", "\n", " \n", "\n", "The files necessary for this assignment are found in a git repository. To turn in this assignment you MUST 'fork' this repository on the MSU github account and add your instructor \"colbrydi@msu.msu.edu\" to your forked repository so he can grade it. Use the following instructions:\n", " \n", "\n", "✅ **DO THIS:** On or before **_February 4th_** Fork the instructor's repository, set the permissions, clone your fork to your HPCC account and make sure you can compile and run the software. Note, this program uses the libpng library which is already installed on the HPCC. \n", " \n", "1. Navigate to the [Edge_Detection git repository](https://gitlab.msu.edu/colbrydi/edge_detection) using your web browser and hit the \"fork\" button (upper right corner) and fork a copy to your personal namespace.\n", "2. Invite your instructor to be a \"member\" of your forked repository by selecting the \"members\" setting (lower left) and inviting entering their email (colbrydi@msu.edu) and setting the role to \"Reporter\". \n", "3. Change your \"Project visibility\" setting to \"private\" which can be found under \"settings\"-->\"General\" and clicking the \"expand\" button next to \"Visibility, project features, permissions\".\n", "4. Copy the URL for your forked repository and paste it to the following online form on or before **_February 4th_**(so your instructor can test permissions):\n", " [Git repository Submission form](https://docs.google.com/forms/d/e/1FAIpQLSfXdNQn4EWU0Z1L3dFaIuoAT4yFdwh3pa5XMo9vy92D2OgI8w/viewform)\n", "5. Clone your forked repository on the HPCC and work from there.\n", "6. Change to the repository and run the following commands to verify the code is working:\n", "```bash\n", "make clean\n", "make\n", "make test\n", "```\n", "7. To complete this assignment commit all of your changes to your forked repository on or before **_11:59pm on Thursday February 25_** \n", " \n", "**_Note:_** if for any reason you can not figure out git, please review the [git tutorial](https://msu-cmse-courses.github.io/cmse802-f20-student/0000-Getting-to-know-git.html) and go to your instructors office hours. If you would like, you may \"tar zip\" (tgz) a backup of your repository to your instructor on the by **_11:59pm on Thursday February 25_**. \n", "\n", "\n", "### Goals for this assignment:\n", "\n", "By the end of this assignment, you should be able to:\n", "\n", "* Practice using Git\n", "* Debug and benchmark existing workflows.\n", "* Using OpenMP to run code in parallel.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Code Description and Background \n", "\n", "There are lots of edge detection algorithms but in this assignment, you will work on an algorithm with the following three steps:\n", "\n", "1. Image Smoothing\n", "2. Gradient calculation (Sobel Filters)\n", "3. Edge Thresholding\n", "\n", "The following section describes each step in detail." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 1: Smoothing (Average vs Median Filtering)\n", "Before starting the actual edge detection, we smooth the image to reduce undesired edges detected due to noise. There are lots of ways to smooth an image. The code provided uses an Average Filter. Average Filtering approaches uses a \"sliding window algorithm\". The input and outputs of a \"sliding window algorithm\" is an image. The value of each pixel in the output image is calculated using a \"window\" of data around the corresponding pixel in the input image. \n", "\n", "For the **Average Filter**, all of the pixels in the window for are averaged and the value is stored in the output image at the same location as the center pixel. \n", "\n", "If you think about it, the sliding window is not fully defined at the edges. For the Average Filter this is not a problem. The algorithm just takes the median or average of the valid points within the windows. Here is a snip-it from the code:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```C++\n", "//Average Filter \n", "for(int c=0;c thresh$$\n", "\n", "The threshold (```thresh```) may be varied to get different results. For the images provided set the threshold to be 50. \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```C++\n", "// Thresholding\n", "for(int c=0;c thresh)\n", " output[r][c] = 255;\n", " else\n", " output[r][c] = 0;\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Homework Assignment\n", "\n", "For this assignment you will do the following parts:\n", "\n", "1. Establish Serial Benchmark\n", "2. Optimize the Serial Code using compiler options\n", "3. Modify the code to use OpenMP loops\n", "4. Final Report\n", "5. Deliverables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 1: Establish Serial Benchmark\n", "\n", "✅ **DO THIS:** Benchmark the code provided using the image files provided in the images directory. This file should provide a solid baseline. Make sure you explicitly describe the hardware you ran on and run enough trials to account for hardware and system variation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 2: Optimize the Serial Code using compiler options\n", "The code provided does not optimized very well. There are lots of things that could be done to speed up the existing code. For this homework I would like you try and benchmark two optimizations:\n", "\n", "1. Use different levels of compiler optimization \n", "1. Change the order of the loops (row and column) for the Average Filter, Gradient Filter and Edge Thresholding. See if the change in order will increase speed due to multiple cache hits. \n", "\n", "✅ **DO THIS:** Make the updates to the serial code as described above. Benchmark and compare the time differences between the original version, the modified versions. Pick the changes that provide for the fastest code. Make all comparisons on the same hardware as Part #1. If possible provide a detailed table or graph to show the differences. \n", "\n", "Make sure you also save a version of your best serial code to turn in. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 3: Modify the code to use OpenMP loops\n", "\n", "✅ **DO THIS:** Rewrite the code to use OpenMP loops to run the Average Filter, Gradient Filter and Edge Thresholding in parallel. Make sure you carefully note the types of changes you make and use proper synchronization. Benchmark your changes with different OMP Loop Scheduling options and compare to the serial benchmarks." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### OMP Loop Scheduling Options\n", "Watch the following video which talks about ways to play around with schedulign options:\n", "\n", "* ✅ **DO THIS:** Watch the Scheduling [Introduction to OpenMP: 10 Discussion 4](https://www.youtube.com/watch?v=8jzHiYo49G0) video:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo(\"8jzHiYo49G0\",width=570,height=360)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ">**schedule(static [,chunk])** Deal-out blocks of interations of size \"chunk\" to each thread\n", "> \n", ">**schedule(dynamic[,chunk])** Each thread grabs \"chunk\" Iterations off a queue until all iterations have been handeled.\n", "> \n", ">**schedule(guided[,chunk])** Threads dynamically grab blocks of iterations. The size of the block starts large and shrinks down to size \"chnunk\" as the calculation proceeds.\n", "> \n", ">**schedule(runtime)** Schedule and chunk size taken from OMP_SCHEDULE enviornment variable (or the runtime library).\n", "> \n", ">**schedule(auto)** Schedule is left up to the runtime to choose (does not have to be any of the above)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Code for loading png images in python\n", "# feel free to load two different version of an edge file, subtract them and compare the difference\n", "# This can be very good when you try to debug. \n", "%matplotlib inline\n", "import matplotlib.pylab as plt\n", "import imageio\n", "\n", "filename = 'Edge_Detection/images/sparty.png'\n", "\n", "im = imageio.imread(filename)\n", " \n", "#Show the image\n", "plt.imshow(im, cmap='gray');\n", "plt.axis('off');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 4: Final Report\n", "\n", "✅ **DO THIS:** Write a report describing what you learned (There is a template in the instructor's git repository). This report should be in the form of a narrative (story). Start by describing how the provided serial code performed and what you did to accurately measure that performance. Then talk about what you did to optimize the serial performance. Finally, describe what you did to add in OpenMP and how the different scheduling options changed the speed of the algorithm. Make sure you include well labeled graphs of all of your benchmarking data and explain the graphs in your report text with a focus on any odd results you may see. Conclude with a general lessons learned.\n", "\n", "This is an image algorithm. You should include example images. \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Grayscale PNG images\n", "The code provided is desinged to work only with grayscale ```*.png``` images. Most PNG images are color and many images are in different formats (ex. TIFF, jpeg). Fortunatly there is an easy to use command called ```convert``` which comes with the [ImageMagick](https://www.imagemagick.org/) Library. Feel free to download and install the software for your own use or use the software already installed on the HPCC. The following examples can be used on the HPCC to load ImageMagick into your PATH, download an image from the internet and convert the image to a grayscale ```PNG``` file:\n", "\n", "```bash\n", "module load ImageMagick\n", "wget https://c1.staticflickr.com/7/6118/6369769483_882a704a38_b.jpg\n", "convert -colorspace Gray 6369769483_882a704a38_b.jpg MSUStadium.png\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 5: Deliverables\n", "\n", "✅ **DO THIS:** Prepare your files for the instructor. I recommend having three versions of the code; original serial version, optimized serial version, optimized OMP version. Update the provided ```Makefile``` to build all three executables. The files should include.\n", "\n", "When you are done, add/commit and push all of your changes to your forked git repository. Your instructor will use the following command to compile and test your code on the HPCC:\n", "\n", " make clean\n", " make \n", " make test\n", "\n", "Watch the following videos for some hints to help streamline your code and benchmarking process:\n", "\n", "✅ **DO THIS:** Environment Variables in OpenMP [Introduction to OpenMP: 11 part 4 Module 6](https://www.youtube.com/watch?v=WXqicIq68-s) \n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo(\"WXqicIq68-s\",width=570,height=360)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 6: Optional Bonus\n", "\n", "✅ **DO THIS:** Create an updated version of the Edge detector which includes some improvement. For example:\n", "\n", "1. Use a median or Gaussian filter instead of the average filter.\n", "2. Use Non-maximum suppression instead of thresholding.\n", "\n", "Learn more about the above options [here](https://web.stanford.edu/class/cs315b/assignment1.html) or pick be creative and try to make something else. \n", "\n", "Make sure the updated code also runs using OpenMP and include it in your Makefile with deliverables. Include the improved edge detection examples in your report. \n", "\n", "Here is a short video about Median Filters. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo(\"3ELsNs4ERY8\",width=640,height=360)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-----\n", "### Congratulations, you are done!\n", "\n", "Submit your tgz file to the course Desire2Learn page in the HW1 assignment. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Written by Dr. Dirk Colbry, Michigan State University\n", "\"Creative
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }
\n", "\"Example\"Example