Workshop 5

Vector Magnitude using Thrust


In this workshop, you calculate the magnitude of a vector using Thrust


Learning Outcomes

Upon successful completion of this workshop, you will have demonstrated the abilities to

  1. operate on a vector on the device using Thrust
  2. code a function object to define a transformation
  3. fuse two transformations into a single transformation
  4. summarize what you think that you have learned in completing this workshop

Specifications

This workshop consists of two separate tasks:

  1. calculating the magnitude of a vector in two transformations:
    1. squaring its elements
    2. adding the squares in a reduction operation
  2. fusing the two transformations to optimize the calculation

Two Part Solution

Square

Define a function class named Square with a call operator.  The operator returns the square of the value received in its parameter and executes on the device. 

magnitude

Define a function named magnitude() that receives a reference to a host vector and returns the magnitude of that vector.  The magnitude is the square root of the sum of the squares of the vector's elements.  This function allocates memory for a device vector of the same size as the host vector, copies the host vector's contents to the device vector, calculates the square of each element on the device, and stores the results in a separate device vector.  This function then calculates the sum of the squared elements using the reduction algorithm

 thrust::reduce(InputIterator first, InputIterator last, (float)0)

Thirdly, your function returns the square root of the sum of the elements squared. 

Source Code

The following partially complete program populates a host vector of user-specified size with random values and calls your magnitude() function to obtain the vector's magnitude.  Complete the missing (highlighted) parts using function calls to the Thrust Template Library.

 // Vector Magnitude - Workshop 5
 // w5.cu

 #include <iostream>
 #include <iomanip>
 #include <cstdlib>
 #include <chrono>
 #include <cstdlib>
 #include <algorithm>
 // insert thrust header files here
 using namespace std::chrono;

 // report system time
 //
 void reportTime(const char* msg, steady_clock::duration span) {
     auto ms = duration_cast<milliseconds>(span);
     std::cout << msg << " - took - " <<
      ms.count() << " millisecs" << std::endl;
 }

 // Square Function Object - add class definition here




 // magnitude - add calculation steps here
 //
 float magnitude(                        ) {
     float result;

     // ... add Thrust calls


     return result;
 }

 int main(int argc, char** argv) {
     if (argc != 2) {
         std::cerr << argv[0] << ": invalid number of arguments\n"; 
         std::cerr << "Usage: " << argv[0] << "  size_of_vector\n"; 
         return 1;
     }
     int n = std::atoi(argv[1]); // number of elements
     steady_clock::time_point ts, te;

     // Thrust definition of host vector


     // initialize the host vector
     ts = steady_clock::now();
     std::generate(     ,     , std::rand);
     te = steady_clock::now();
     reportTime("initialization", te - ts);

     // calculate the magnitude of the host vector
     ts = steady_clock::now();
     float len = magnitude(     );
     te = steady_clock::now();
     reportTime("magnitude calculation", te - ts);

     // display the magnitude
     std::cout << std::fixed << std::setprecision(4);
     std::cout << "Magnitude : " << len << std::endl;
 }

Run the executable for the following vector sizes and record the timing for the magnitude calculation.

n Two Part
5000000  
10000000  
15000000  
20000000  

Fused Solution

Upgrade your magnitude() function to perform the squaring and summation in one fused step.  Use the following algorithm from Thrust:

 thrust::transform_reduce(InputIterator first, InputIterator last, operation,
  (float)0, plus<float>())

Rerun the executable for the following vector sizes and record the timing statistics alongside your previous results.

n Two Part Fused
5000000    
10000000    
15000000    
20000000    

Report

Record the elapsed times on a spreadsheet named w5.ods or w5.xls in the form of the table shown above. 

Prepare a 3D look realistic column chart plotting the elapsed times for the two-part and fused solutions against n along the horizontal axis as shown below. 

Chart

You can create the chart in Open Office using the following steps:

  • Highlight data and labels
  • Select Chart in the Toolbar
  • Chart Type - check 3D Look Realistic Column
  • Data Range - 1st row as label, 1st column as label
  • Chart Elements - add title, subtitle, axes labels

You can create the chart in Excel using the following steps:

  • Select Insert Tab -> Column -> 3D Clustered Column
  • Select Data -> remove n -> select edit on horizontal axis labels -> add n column
  • Select Chart tools -> Layout -> Chart Title - enter title and subtitle
  • Select Chart tools -> Layout -> Axis Titles -> Select axis - enter axis label

Save your chart as part of your spreadsheet file.


SUBMISSION

Copy the results of your tests for both versions into a file named w5.txt.  This file should include

  • your userid
  • a listing of your two part version
  • output from running your two part version
  • a listing of your fused version
  • output from running your fused version

Upload your typescript to Blackboard: 

  • Login to
  • Select your course code
  • Select Workshop 5 under Workshops
  • Upload w5.txt and w5.ods or w5.xls
  • Under "Add Comments" write a short note to your instructor:  Add a sentence or two describing what you think you have learned in this workshop.
  • When ready to submit, press "Submit"






  Designed by Chris Szalwinski   Copying From This Site   
Logo
Creative Commons License