Skip to content

Example: Argument Passing

Grauniad edited this page May 29, 2014 · 1 revision

WARNING: This page is UNDER CONSTRUCTION

This is simple introductory tutorial using Callgrind and CGV to profile a c++ binary.

It assumes you have built CGV, and have installed valgrind, and a modern C++ compiler. If you haven't done this yet checkout the getting started page.

Building the example

Navigate to the example directory, and run make. It's a two-liner so feel free to change out g++ for your compiler of choice...

# Build the example
>>> make
g++-4.8.2 -g -O3 -march=native -o sums -std=c++11 main.cpp sums.cpp

# Collect the callgrind data
>>> ../../gather.sh ./sums
==10214== Callgrind, a call-graph generating cache profiler
==10214== Copyright (C) 2002-2012, and GNU GPL'd, by Josef Weidendorfer et al.
==10214== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==10214== Command: ./sums
==10214== 
==10214== For interactive control, run 'callgrind_control -h'.
==10214== 
==10214== Events    : Ir
==10214== Collected : 1327625
==10214== 
==10214== I   refs:      1,327,625

# Start CGV
>>> ../../profile gather.out 
Building call graph...done
Process started up in 5 mili-seconds
|ROOT> 

By default we're placed into the ROOT (just above main) node. If you run the 'tree' command from here you can see you entire program branch out.

|ROOT> tree 2
  ROOT
      Calls: 0, Time: 0, Av. Time: 0
      main
          Calls: 1, Time: 62951, Av. Time: 62951
          vector(int const&, int const&, int const&, int const&, int const&)
              Calls: 1, Time: 62743, Av. Time: 62743
          c_style(int const&, int const&, int const&, int const&, int const&)
              Calls: 1, Time: 85, Av. Time: 85
          initializer(int const&, int const&, int const&, int const&, int const&)
              Calls: 1, Time: 39, Av. Time: 39
          array(int const&, int const&, int const&, int const&, int const&)
              Calls: 1, Time: 11, Av. Time: 11
          templ(int const&, int const&, int const&, int const&, int const&)
              Calls: 1, Time: 6, Av. Time: 6
          basic(int const&, int const&, int const&, int const&, int const&)
              Calls: 1, Time: 6, Av. Time: 6

|ROOT> 

In the interests of space, I've limited the maximum depth of the graph in the above example to 2.

The problem

We want a function which takes a variable number of arguments (let's say ints) and returns their sum. We will use this hard-coded function has a benchmark.

|ROOT> searchchildren basic
 --> main/basic(int const&, int const&, int const&, int const&, int const&) : 6.000000e+00 / 1 (6)
There are 0 more results
|basic> annotate
   10:            ( 0%): int sum(const int& i1,
   11:            ( 0%):         const int& i2,
   12:            ( 0%):         const int& i3,
   13:            ( 0%):         const int& i4,
   14:            ( 0%):         const int& i5)
   15:            ( 0%): {
   16:          5 !83%!:     return i1 + i2 + i3 + i4 + i5;
   17:            ( 0%): }
   18:            ( 0%):
   19:            ( 0%): int basic(const int& i1,
   20:            ( 0%):             const int& i2,
   21:            ( 0%):             const int& i3,
   22:            ( 0%):             const int& i4,
   23:            ( 0%):             const int& i5)
   24:            ( 0%): {
   25:            ( 0%):     return sum(i1,i2,i3,i4,i5);
   26:          1 (16%): }

I'm using a release binary ( g++ -g -O3 -march=native main.cpp sums.cpp). In the interest of fairness, each function is called from an outer function with identical signatures.

The example code is provided in the CGV source.

Option 1: The old fashioned way

While c didn't support it function overloading, it did bequeath C++ the var_arg method variable argument functions:

/**************************************
* c-style var args: 85 Reads (x14.1)
*************************************/
int varsum(const int& n, ...)
{
    va_list vl;
    va_start(vl,n);
    int s = 0;
    for ( int i = 0; i< n; ++i) {
        s += va_arg(vl,int);
    }
    va_end(vl);
    return s;
}

The va_* functions are actually just clever macros which allow the function to pull as many arguments as it likes off the stack.

Clone this wiki locally