Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

57
Pragmatic Programmer on Meta Programming Tip 29 Write Code that Writes Code. - The Pragmatic Programmer, Hunt and Thomas,[1] P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 0 / 28

description

Talk given at the Dec 12th, 2013, Dresden (Germany) C++ User group meeting. The slides discuss 2 widely used approaches to develop C++ libraries and applications in a modular (object oriented) and yet very high performant fashion. A basic knowledge of C++ templating techniques is assumed of the reader.

Transcript of Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Page 1: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Pragmatic Programmer on Meta Programming

Tip 29

Write Code that Writes Code.- The Pragmatic Programmer, Hunt and Thomas,[1]

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 0 / 28

Page 2: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Lightweight Abstractions in C++

- An Introduction to CRTP and Expression Templates -

Peter Steinbach

Scientific Computing FacilityMax Planck Institute of Molecular Cell Biology and Genetics

Dec 12nd, 2013

Page 3: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Outline

1. Motivation

2. Performant Inheritance

3. Expressive And Fast Calculations

4. The Case of Eigen

5. Summary

6. Appendix

7. Literature

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 2 / 28

Page 4: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Outline

1. Motivation

2. Performant Inheritance

3. Expressive And Fast Calculations

4. The Case of Eigen

5. Summary

6. Appendix

7. Literature

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 3 / 28

Page 5: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Motivation : Why Abstractions?

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 4 / 28

Page 6: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Motivation : Why Abstractions?

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 4 / 28

Page 7: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Motivation : The Following Slides ...

Abstractions in C++

Disclaimer

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 5 / 28

Page 8: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Outline

1. Motivation

2. Performant Inheritance

3. Expressive And Fast Calculations

4. The Case of Eigen

5. Summary

6. Appendix

7. Literature

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 6 / 28

Page 9: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: Virtual Inheritance Example

root.cern.ch[2]

ROOT TH1D

one-dimensional histogram with double precisiondata

extensive use of virtual inheritance

overloaded with responsibilities

to be fair: late 1990s, early 2000s

List of virtual functions fills six A4 pages!

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 7 / 28

Page 10: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: Virtual Inheritance Example

root.cern.ch[2]

ROOT TH1D

one-dimensional histogram with double precisiondata

extensive use of virtual inheritance

overloaded with responsibilities

to be fair: late 1990s, early 2000s

List of virtual functions fills six A4 pages!

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 7 / 28

Page 11: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: Virtual Inheritance Recap

1 class AbstrBase

{

3 public:

virtual unsigned update(const unsigned& _in)

const = 0;

5 };

7 class Derived: public AbstrBase

{

9 public:

unsigned update(const unsigned& _in) const {

11 return _in - 1;

}

13 };

dynamic polymorphism

function pointers to available implementations stored on stack

pointers resolved through table ( vtable)

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 8 / 28

Page 12: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: Virtual Inheritance Experiment

1 unsigned count_down(

AbstrBase* _updater ,

3 const unsigned& _start_index

){

5

unsigned i = _start_index;

7 for(;i>0;){

i = _updater ->update(i);

9 }

return i;

11 }

g++ -O3, 230 → 0

t = 2.1 s

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 9 / 28

Page 13: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: Virtual Inheritance Experiment

1 unsigned count_down(

AbstrBase* _updater ,

3 const unsigned& _start_index

){

5

unsigned i = _start_index;

7 for(;i>0;){

i = _updater ->update(i);

9 }

return i;

11 }

g++ -O3, 230 → 0

t = 2.1 s

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 9 / 28

Page 14: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: Curiously Recurring Template Pattern

1 template <typename Daughter >

struct CRTPBase {

3 int update(const int& _in) const {

return Daughter :: do_update(_in);

5 }

7 };

9 struct CRTPDerived : public CRTPBase <CRTPDerived >

{

11 int do_update(const int& _in) const {

return _in - 1;

13 }

};

first discussed in 1995 [3]

sub-templated Design-by-Policy implementation [4]

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 10 / 28

Page 15: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

template <typename Daughter >

2 struct CRTPBase {

int update(const int& _in) const {

4 return Daughter :: do_update(_in);

}

6

};

8

struct CRTPDerived : public CRTPBase <CRTPDerived >

10 {

int do_update(const int& _in) const {

12 return _in - 1;

}

14 };

CRTPDerived

declared

CRTPBase

instantiated

CRTPBase::update

declarationinstantiated

CRTPDerived defined

CRTPDerived defined

CRTPBase::update

definition instantiatedif needed

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 11 / 28

Page 16: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

template <typename Daughter >

2 struct CRTPBase {

int update(const int& _in) const {

4 return Daughter :: do_update(_in);

}

6

};

8

struct CRTPDerived : public CRTPBase <CRTPDerived >

10 {

int do_update(const int& _in) const {

12 return _in - 1;

}

14 };

CRTPDerived

declared

CRTPBase

instantiated

CRTPBase::update

declarationinstantiated

CRTPDerived defined

CRTPDerived defined

CRTPBase::update

definition instantiatedif needed

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 11 / 28

Page 17: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

template <typename Daughter >

2 struct CRTPBase {

int update(const int& _in) const {

4 return Daughter :: do_update(_in);

}

6

};

8

struct CRTPDerived : public CRTPBase <CRTPDerived >

10 {

int do_update(const int& _in) const {

12 return _in - 1;

}

14 };

CRTPDerived

declared

CRTPBase

instantiated

CRTPBase::update

declarationinstantiated

CRTPDerived defined

CRTPDerived defined

CRTPBase::update

definition instantiatedif needed

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 11 / 28

Page 18: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

template <typename Daughter >

2 struct CRTPBase {

int update(const int& _in) const {

4 return Daughter :: do_update(_in);

}

6

};

8

struct CRTPDerived : public CRTPBase <CRTPDerived >

10 {

int do_update(const int& _in) const {

12 return _in - 1;

}

14 };

CRTPDerived

declared

CRTPBase

instantiated

CRTPBase::update

declarationinstantiated

CRTPDerived defined

CRTPDerived defined

CRTPBase::update

definition instantiatedif needed

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 11 / 28

Page 19: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

template <typename Daughter >

2 struct CRTPBase {

int update(const int& _in) const {

4 return Daughter :: do_update(_in);

}

6

};

8

struct CRTPDerived : public CRTPBase <CRTPDerived >

10 {

int do_update(const int& _in) const {

12 return _in - 1;

}

14 };

CRTPDerived

declared

CRTPBase

instantiated

CRTPBase::update

declarationinstantiated

CRTPDerived defined

CRTPDerived defined

CRTPBase::update

definition instantiatedif needed

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 11 / 28

Page 20: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

template <typename Daughter >

2 struct CRTPBase {

int update(const int& _in) const {

4 return Daughter :: do_update(_in);

}

6

};

8

struct CRTPDerived : public CRTPBase <CRTPDerived >

10 {

int do_update(const int& _in) const {

12 return _in - 1;

}

14 };

CRTPDerived

declared

CRTPBase

instantiated

CRTPBase::update

declarationinstantiated

CRTPDerived defined

CRTPDerived defined

CRTPBase::update

definition instantiatedif needed

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 11 / 28

Page 21: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

template <typename T>

2 unsigned count_down(const T& _updater ,

const unsigned& _start_index

4 ){

unsigned i = _start_index;

6 for(;i>0;)

i = _updater.update(i);

8 return i;

}

g++ -O3, 230 → 0

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 12 / 28

Page 22: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

1 template <typename T>

unsigned count_down(const T& _updater ,

3 const unsigned& _start_index

){

5 unsigned i = _start_index;

for(;i>0;)

7 i = _updater.update(i);

return i;

9 }

g++ -O3, 230 → 0

Any Guesses?

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 12 / 28

Page 23: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: CRTP = strange name

1 template <typename T>

unsigned count_down(const T& _updater ,

3 const unsigned& _start_index

){

5 unsigned i = _start_index;

for(;i>0;)

7 i = _updater.update(i);

return i;

9 }

g++ -O3, 230 → 0

t = 0 s

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 12 / 28

Page 24: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: What’s going on?

1 template <typename Daughter >

class CRTPBase {

3 public:

int update(const int& _in) const {

5 return Daughter :: do_update(_in);

}

7 };

0 s . . . a bug?

compiler simply emitted no code for crtp count down

optimisation schemes dropped redundant operationsimpossible with dynamic polymorphism

vtable incurs branching (virtual = 1000x branchesthan crtp)for loop acutally performed including indirectionthrough inheritance

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 13 / 28

Page 25: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

CRTP: Wrap-Up

1 template <typename Daughter >class CRTPBase {

3 public:int update(const int& _in) const {

5 return Daughter :: do_update(_in);}

7 };

Pros and Cons

code reuse through common base class interface

flexibility of class composition retained

open for compiler optimisations

functionality through class communication (OO design)

compiler aided removal of virtual inheritance-fdevirtualize [5]

price: no runtime flexibility

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 14 / 28

Page 26: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Outline

1. Motivation

2. Performant Inheritance

3. Expressive And Fast Calculations

4. The Case of Eigen

5. Summary

6. Appendix

7. Literature

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 15 / 28

Page 27: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: Adding two Vectors

cBLAS

1 double a[4] = {2, 3, 4, 5};

double b[4] = {5, 4, 9, 2};

3 //b <- 1.0*a + b

cblas_daxpy (4, 1.0, a, 1, b, 1);

Taken from http://www.mitchr.me/SS/exampleCode/blas/blas1C.c.html

Something readable would be nice!

Vector a(N), b(N), c(N);

2 //fill Vector(s) a and b

c = a + b;

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 16 / 28

Page 28: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: Adding two Vectors

cBLAS

1 double a[4] = {2, 3, 4, 5};

double b[4] = {5, 4, 9, 2};

3 //b <- 1.0*a + b

cblas_daxpy (4, 1.0, a, 1, b, 1);

Taken from http://www.mitchr.me/SS/exampleCode/blas/blas1C.c.html

Something readable would be nice!

Vector a(N), b(N), c(N);

2 //fill Vector(s) a and b

c = a + b;

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 16 / 28

Page 29: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: A Standard Implementation

1 inline const Vector operator +(

const Vector& _first ,

3 const Vector& _second){

5 Vector temporary(_first.size());

7 for(size_t index = 0; index < _first.size();++

index)

temporary[index] = _first[index] + _second[

index];

9

return temporary;

11 }

Issues

large vectors: temporary becomes the bottleneck

large vectors: sum will always be carried out entirely

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 17 / 28

Page 30: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: A Standard Implementation

1 inline const Vector operator +(

const Vector& _first ,

3 const Vector& _second){

5 Vector temporary(_first.size());

7 for(size_t index = 0; index < _first.size();++

index)

temporary[index] = _first[index] + _second[

index];

9

return temporary;

11 }

Issues

large vectors: temporary becomes the bottleneck

large vectors: sum will always be carried out entirely

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 17 / 28

Page 31: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: Store Operations, not Data

1 template <typename A, typename B>

class sum {

3 const A& left_;

const B& right_;

5 public:

explicit sum(const A& _left ,const B& _right):

7 left_(_left), right_(_right){}

9 size_t size() const {

return left_.size();

11 }

13 double operator []( size_t _index) const {

return left_[index] + right_[index];

15 }

};

sum is cheap in terms of memory (2 references inside)

stores and passes the operation of one element

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 18 / 28

Page 32: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: Store Operations, not Data

template <typename A, typename B>

2 class sum {

const A& left_;

4 const B& right_;

public:

6 explicit sum(const A& _left ,const B& _right):

left_(_left), right_(_right){}

8

size_t size() const {

10 return left_.size();

}

12

double operator []( size_t _index) const {

14 return left_[index] + right_[index];

}

16 };

sum is cheap in terms of memory (2 references inside)

stores and passes the operation of one element

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 18 / 28

Page 33: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: Store Operations, not Data

template <typename A, typename B>

2 class sum {

const A& left_;

4 const B& right_;

public:

6 explicit sum(const A& _left ,const B& _right):

left_(_left), right_(_right){}

8

size_t size() const {

10 return left_.size();

}

12

double operator []( size_t _index) const {

14 return left_[index] + right_[index];

}

16 };

sum is cheap in terms of memory (2 references inside)

stores and passes the operation of one element

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 18 / 28

Page 34: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: Vector needs to be extended

class Vector{

2 //...

template <typename T>

4 Vector& operator =( const T& _in){

resize( _in.size() );

6

for(size_t index = 0;index <_in.size();++ index

)

8 v_[index] = _in[index];

10 return (*this);

}

12 //...

};

added new assignment operator to Vector

just an example of interfacing Vector with sum

required for (c = a + b)

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 19 / 28

Page 35: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: Harvesting the Fruit

1 Vector a(N), b(N), c(N);

//fill Vector(s) a and b

3 a + b; //0 additions

(a+b)[0]; //1 addition

5

c = a + b; //N additions

no memory overhead by temporaries

achieved lazy evaluation (operation is conduction once it isreally needed)

intermediate abstraction has small memory foot print

syntax is expressive and readable

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 20 / 28

Page 36: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

ExprTempl: Runtime Improvements

Performance of vector additions using different C++ implementations from [6].

There is more . . .

expression templates first reported in 1995 [7]

same scheme can be applicable in many more fields

expression templates allow modular jump-in of acceleratorcode

used by: Eigen [8], Blaze[9], MTL4[10] . . .

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 21 / 28

Page 37: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Outline

1. Motivation

2. Performant Inheritance

3. Expressive And Fast Calculations

4. The Case of Eigen

5. Summary

6. Appendix

7. Literature

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 22 / 28

Page 38: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Eigen: What is it?

for linear algebra, matrix and vector operations,numerical solvers and related algorithms

header-only library complying C++98 standard

performed for SSE 2/3/4, ARM NEON, andAltiVec instruction sets and non-vectorizedimplementations

open source under Mozilla Public License v2

for details visit [8]

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 23 / 28

Page 39: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Eigen: Vector Addition Again

Eigen :: VectorXf u(size), v(size), w(size);

2 u = v + w;

MatrixBase

Derived:typename

VectorXf

CRTP

CwiseBinaryOp

BinaryOp:typename

LHS:typename

RHS:typename

CRTP

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 24 / 28

Page 40: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Eigen: Vector Addition Real-Life

Eigen :: VectorXf u(size), v(size), w(size);

2 u = v + w;

MatrixBase

+operator=()

Derived:typename

VectorXf

CRTP

CwiseBinaryOp

BinaryOp:typename

LHS:typename

RHS:typename

CRTP

internal::assign_selector

+run(dst:Derived,other:OtherDerived)

Derived:T

OtherDerived:T

internal::assign_impl

+run(dst:Derived,other:OtherDerived)

Derived:T

OtherDerived:T

internal::pload internal::padd internal::pstore

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 25 / 28

Page 41: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Outline

1. Motivation

2. Performant Inheritance

3. Expressive And Fast Calculations

4. The Case of Eigen

5. Summary

6. Appendix

7. Literature

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 26 / 28

Page 42: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Summary

C++ template engine provides tools for lightweightabstractions

CRTP can replace virtual inheritance at runtime

expression templates reduce the need for temporariesand more

revisit your code and wonder, what portions arecompile time constants

Tip 29

Write Code that Writes Code.

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 27 / 28

Page 43: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Summary

C++ template engine provides tools for lightweightabstractions

CRTP can replace virtual inheritance at runtime

expression templates reduce the need for temporariesand more

revisit your code and wonder, what portions arecompile time constants

Tip 29

Write Code that Writes Code.

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 27 / 28

Page 44: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Final Word

from [11]

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 28 / 28

Page 45: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Final Word

from [11]

Thank you for your attention!

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 28 / 28

Page 46: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Outline

1. Motivation

2. Performant Inheritance

3. Expressive And Fast Calculations

4. The Case of Eigen

5. Summary

6. Appendix

7. Literature

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 29 / 28

Page 47: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: Templates Recap

template <typename T>

2 T add(const T& _first , const T& _second) {

return _first + _second;

4 }

C++ templates processed by template engine before compilation intobinary

templates and template engine form a Turing-complete programminglanguage [12]

using C++ templates for Meta Programming:

C++ Template Meta Programming

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 30 / 28

Page 48: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: Templates Recap

template <typename T>

2 T add(const T& _first , const T& _second) {

return _first + _second;

4 }

C++ templates processed by template engine before compilation intobinary

templates and template engine form a Turing-complete programminglanguage [12]

using C++ templates for Meta Programming:

C++ Template Meta Programming

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 30 / 28

Page 49: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: Templates Recap

template <typename T>

2 T add(const T& _first , const T& _second) {

return _first + _second;

4 }

C++ templates processed by template engine before compilation intobinary

templates and template engine form a Turing-complete programminglanguage [12]

using C++ templates for Meta Programming:

C++ Template Meta Programming

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 30 / 28

Page 50: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: Factorial At Runtime

unsigned int runtime_factorial(unsigned int n

){

2 if ( n == 0)

return 1;

4 else

return n * runtime_factorial(n-1):

6 }

If argument known at compile time,calculate it at compile time!

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 31 / 28

Page 51: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: Factorial At Compile Time

template <size_t n>

2 struct static_factorial {

static const size_t value = n *

static_factorial <n - 1>::value ;

4 };

6 template <>

struct static_factorial <0> {

8 static const size_t value = 1 ;

};

Classical example from [13].

input parameters required at compile time (implies static constness)

result known at compile time already, no runtime investment

these days CPU are so fast, this example is more academic

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 32 / 28

Page 52: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: Factorial At Compile Time

template <size_t n>

2 struct static_factorial {

static const size_t value = n *

static_factorial <n - 1>::value ;

4 };

6 template <>

struct static_factorial <0> {

8 static const size_t value = 1 ;

};

Classical example from [13].

input parameters required at compile time (implies static constness)

result known at compile time already, no runtime investment

these days CPU are so fast, this example is more academic

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 32 / 28

Page 53: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: Factorial At Compile Time

template <size_t n>

2 struct static_factorial {

static const size_t value = n *

static_factorial <n - 1>::value ;

4 };

6 template <>

struct static_factorial <0> {

8 static const size_t value = 1 ;

};

Classical example from [13].

input parameters required at compile time (implies static constness)

result known at compile time already, no runtime investment

these days CPU are so fast, this example is more academic

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 32 / 28

Page 54: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: VTable

clang -cc1 -fdump-record-layouts virtual_sizeof.cpp

*** Dumping AST Record Layout0 | class Derived0 | class AbstrBase (primary base)0 | (AbstrBase vtable pointer)0 | (AbstrBase vftable pointer)

| [sizeof=8, dsize=8, align=8| nvsize=8, nvalign=8]

clang -cc1 -fdump-record-layouts crtp_sizeof.cpp

*** Dumping AST Record Layout0 | class CRTPDerived (empty)0 | class CRTPBase<class CRTPDerived> (base) (empty)

| [sizeof=1, dsize=0, align=1| nvsize=1, nvalign=1]

Back to Virtual Inheritance Recap.

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 33 / 28

Page 55: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Appendix: Disclaimer

All images (except stated otherwise) in this presentationwere taken from the OpenClipArt gallery and are subject

to the public domain. Seehttp://openclipart.org/share for more information

on sharing terms.

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 34 / 28

Page 56: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Outline

1. Motivation

2. Performant Inheritance

3. Expressive And Fast Calculations

4. The Case of Eigen

5. Summary

6. Appendix

7. Literature

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 35 / 28

Page 57: Lightweight Abstractions in C++, An Introduction to CRTP and Expression Templates

Literature

[1] A. Hunt and D. Thomas, The Pragmatic Programmer.Addison and Wesley, 2000.

[2] R. Brun and F. Rademakers, “Root - an object oriented data analysis framework,” in Proceedings AIHENP’96 Workshop, vol. A of Nucl. Inst. &Meth. in Phys. Res., pp. 81–86, September 1996.http://root.cern.ch.

[3] J. O. Coplien, “Curiously recurring template pattern,” in C++ Report, pp. 24–27, February 1995.

[4] A. Alexandrescu, Modern C++ Design: Generic Programming and Design Patterns Applied.Addison-Wesley, 2001.

[5] E. Bendersky, “http://eli.thegreenplace.net/2013/12/05/the-cost-of-dynamic-virtual-calls-vs-static-crtp-dispatch-in-c/.”interesting performance evalution of CRTP.

[6] K. Iglberger, G. Hager, J. Treibig, and U. RA 14

de, “Expression templates revisited: A performance analysis of current methodologies,” SIAM Journal

on Scientific Computing, vol. 34, no. 2, pp. C42–C69, 2012.

[7] T. Veldhuizen, “Expression templates,” in C++ Report, vol. 5, pp. 26–31, June 1995.

[8] “Eigen.” http://eigen.tuxfamily.org/index.php?title=Main_Page.C++ library of template headers for linear algebra, matrix and vector operations, numerical solvers and related algorithms.

[9] “Blaze-lib.”http://code.google.com/p/blaze-lib/.

[10] “Mtl4 - matrix template library.”http://www.simunova.com/de/node/24.

[11] K. Rocki, M. Burtscher, and R. Suda, “The future of accelerator programming: Abstraction, performance or can we have both?,” 2014.http://olab.is.s.u-tokyo.ac.jp/~kamil.rocki/pub.html.

[12] “Proving turing-completeness of c++ templates.”http://matt.might.net/articles/c++-template-meta-programming-with-lambda-calculus/.

[13] “Template metaprogramming.”http://en.wikipedia.org/wiki/Template_metaprogramming.

[14] “http://talesofcpp.fusionfenix.com/post-12/episode-eight-the-curious-case-of-the-recurring-template-pattern.”

P. Steinbach (MPI CBG) LightAbstractions Dec 12nd, 2013 36 / 28