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 #include #include #include #include #include // 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(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 << ": invalid number of arguments\n";  std::cerr << "Usage: " << argv << " size_of_vector\n";  return 1; } int n = std::atoi(argv); // 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. 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

SUBMISSION

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

• 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  