Last Updated: 2026-04-24 Fri 11:34

CMSC216 HW10: Timing Reversals

Homeworks are optional practice with no submission and no credit

CODE DISTRIBUTION: hw10-code.zip

  • Download the code distribution every HW
  • See further setup instructions below

CHANGELOG: Empty

1 Rationale

When studying the performance of code, it is important to time using functions like clock() and gettimeofday() so that suspicions about memory and cache behavior are backed by empirical data. Automating benchmarks of code is best handled using build systems like make. This HW focusing on evaluating a few functions to reverse and array for their speed, timing those run and automating the process.

1.1 Associated Reading / Preparation

Bryant and O'Hallaron: Ch 6 on The Memory Hierarchy. Ch 6.5 and 6.6 may be particularly helpful to understanding cache effects.

Tutorials on Makefiles abound with some coverage in a recent lab. Those wanting a more complete account should consult the GNU Make Manual as it is the most widely deployed implementation of make and its manual is thorough.

1.2 Grading Policy

Homework provides optional extra practice for students looking for it. No submission is collected and the HW is not worth any course credit. Solutions will be posted some time after the HW is posted. Students approaching course staff for additional practice problems will be asked to explain their own written answers to the QUESTIONS.txt documents in HWs before any additional problems will be constructed.

2 Codepack

The codepack for the HW contains the following files:

File State Description
QUESTIONS.txt Edit Answer questions in the file to complete the HW
reverse_benchmark.c Edit Problem 1 source file to analyze/edit
Makefile Create Problem 1 build file to create according to instructions

3 Questions

                           _________________

                            HW 10 QUESTIONS
                           _________________


HWs are optional practice and there is no submission.


PROBLEM 1: Timing Benchmarks
============================

  The code in `reverse_benchmark.c' implements two functions which
  reverse the elements of an array. They take different approaches.
  ,----
  | void reverse_arr1(int *arr, long size){
  |   int *tmp = malloc(sizeof(int)*size);
  |   for(long i=0; i<size; i++){
  |     tmp[i] = arr[size-i-1];
  |   }
  |   for(long i=0; i<size; i++){
  |     arr[i] = tmp[i];
  |   }
  |   free(tmp);
  | }
  | 
  | void reverse_arr2(int *arr, long size){
  |   for(long i=0; i<size/2; i++){
  |     int tmp = arr[i];
  |     arr[i] = arr[size-i-1];
  |     arr[size-i-1] = tmp;
  |   }
  | }
  `----


(A) Predictions
~~~~~~~~~~~~~~~

  Predict which of these two functions will run faster based on their
  code characteristics. Justify your answer by contrasting the features
  of the two reversal functions.


(B) Timing
~~~~~~~~~~

  Complete the provided `reverse_benchmark.c' file by filling in code
  that will repeatedly run the two functions above and print times for
  them. The runs will be on increasing sizes of arrays. When the code is
  complete, manually compile and run the benchmark to investigate some
  times and either confirm or support your suspicions on speed. Measure
  elapsed CPU time, not than real/wall time.


(C) Makefile
~~~~~~~~~~~~

  Write a small Makefile to automate building and evaluating the
  system. The Makefile should have the following targets.
  - `all' the default target, builds `reverse_benchmark' and then prints
    to the screen `Ready to reverse'
  - `reverse_benchmark' which depends on `reverse_benchmark.c' and
    compiles it using the following GCC options: `-g -Og'
  - `run' depends on `reverse_benchmark' and does two runs of the
    benchmark:
    1. Echoes "Running large with 1 repetition" then runs
       `./reverse_benchmark 22 26 1'
    2. Echoes "Running small with 100 repetitions" then runs
       `./reverse_benchmark 20 24 100'
  - Clean which removes `reverse_benchmark' and any `.o' files that are
    around

  Test out the Makefile to ensure it performs correctly: such as what is
  shown in the following session.

  ,----
  | >> make clean
  | rm -f reverse_benchmark *.o
  | 
  | >> make run
  | gcc -g -Og -o reverse_benchmark reverse_benchmark.c
  | Running large with 1 repetition
  | ./reverse_benchmark 22 26 1
  |       SIZE     rev1     rev2 
  |    4194304  0.01025  0.00693 
  |    8388608  ...
  |    ...
  | Running small with 100 repetitions
  | ./reverse_benchmark 20 24 100
  |       SIZE     rev1     rev2 
  |    1048576  0.14696  0.05640 
  |    2097152  ...
  |    ...
  | 
  | >> make clean
  | rm -f reverse_benchmark *.o
  | 
  | >> make
  | gcc -g -Og -o reverse_benchmark reverse_benchmark.c
  | Ready to benchmark
  | 
  | >> make run
  | Running large with 1 repetition
  | ./reverse_benchmark 22 26 1
  |       SIZE     rev1     rev2 
  |    4194304  0.01108  0.00359 
  |    8388608  ...
  |    ...
  | Running small with 100 repetitions
  | ./reverse_benchmark 20 24 100
  |       SIZE     rev1     rev2 
  |    1048576  0.14349  0.05626 
  |    2097152  ...
  |    ...
  | >> make
  | Ready to benchmark
  `----


(D) Analysis
~~~~~~~~~~~~

  Clean the code, build it, and do a `make run' on Zaratan. Examine the
  timing information to see if the timing results support your
  suspicions from earlier. Paste your completed timing results below.

Author: Chris Kauffman (profk@umd.edu)
Date: 2026-04-24 Fri 11:34