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
- operate on a vector on the device using Thrust
- code a function object to define a transformation
- fuse two transformations into a single transformation
- summarize what you think that you have learned in completing this workshop
Specifications
This workshop consists of two separate tasks:
- calculating the magnitude of a vector in two transformations:
- squaring its elements
- adding the squares in a reduction operation
- 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.

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"
|