Mayank Jain Production Engineer at Facebook Inc.

Functors in C++ - Part II

This post is in continuation to Functors in C++ - Part I.

In last blog we talked about basics of functors. In this post let’s dive deep into functors and talk about some application of functors.

Functors are commonly used in STL algorithms. The power of functors can clearly be realised when we use them with STL.

STL Functors

There is one more good thing to this whole story. We don’t have to write all functors by ourselves. STL provides some built-in functors for basic operations like addition, divison, some bitwise operators etc. Some of the STL Functors are^:

  • Binary Arithmetic Functors : plus (for addition, equivalent to arg1 + arg2), minus (for subtraction, same as arg1 - arg2 ), divides (division) etc. ^^
  • Binary Logical Functors : logical_and, logical_or
  • Unary Functors : negate, logical_not.

Binary functors are functors those take two parameters while unary take only one parameter.

^ Complete list and their descriptions can be found here.
^^ arg1 and arg2 are two input parameters to functors. Example: std::plus<int>()(arg1 + arg2)

Let’s take a example here. Assume we need to multiply each element of vector by -1. This can be done very easily as:

// Compile this code with -std=c++11 flag.
// like: g++ -std=c++11 main.cpp

#include<vector>
#include<algorithm>
#include<functional>
#include<iostream>

int main(){

        // Initializing vector with 1,2 and 3 as it's elements
        std::vector<int> vec = {1,2,3};

        // Transforming each element of vector by multiplying 
	// it with -1. First argument to std::Transform is 
	// start iterator. Second argument is end iterator
        // Third argument says where we need to store the 
	// result. Here we are storing result in vec itself.
        // And the last argument says which functor do we 
	// need to call for each element of vector from 
	// start iterator to end iterator
        std::transform(vec.begin(),vec.end(),
		vec.begin(),std::negate<int>());

        // print the transformed vector
        for(int i=0;i<vec.size();i++){
                std::cout << vec[i] << ' ';
        }
        // output would be
        // -1 -2 -3
}

It’s so easy and much more readble than doing same thing without using STL. Isn’t it!?

But we do have one problem here if we use binary functor with std::transform instead of unary functor. Binary functor takes two input arguments while std::transform expects functor with just one argument. In this scenario std::bind can be useful.

Bind

Let’s take a example where we need to add 5 to each element of std::vector, vec1 and store the result in another vector named vec2. How can this be done using std::transform and std::plus?

Here’s the solution:

// Compile this code with -std=c++11.
// g++ -std=c++11 main.cpp

#include<vector>
#include<algorithm>
#include<functional>
#include<iostream>

#define ELEM_TO_ADD 5

int main(){

        // Initializing vector with 1,2 and 3 as three elements
        std::vector<int> vec1 = {1,2,3};
        std::vector<int> vec2;

        std::transform(vec1.begin(),vec1.end(),
			std::back_inserter(vec2),
                        std::bind(std::plus<int>(),
				std::placeholders::_1,
				ELEM_TO_ADD)
		      );

        // print the transformed vector
        for(int i=0;i<vec2.size();i++){
                std::cout << vec2[i] << ' ';
        }
        // output would be
        // 6 7 8
}

Let’s try to understand logic of above piece of code. std::transform as discussed previously invoke the functor (specified by last argument) for each element iterating from vec1.begin() to vec1.end(). Before moving forward let’s first understand what std::bind does.

std::bind is partial function application. What this means is suppose you have a function func1 which takes two args as func1(arg1,arg2).

Now, you want to define a new function func2 as:

func2(arg1){
	func1(arg1,5)
}

func2 has been defined by fixing argument arg2, so func2 is said as partial application of func1. std::bind does same. In terms of C++ STL func2 can be defined as:

auto func2 = std::bind(func1,std::placeholders::_1,5)

What we are saying by above line is: Create func2 by binding func1, first argument of func1 (specified as, std::placeholders::_1) and 5.^

^std::placeholders::_1 means first argument, std::placeholders::_2 means second parameter and so on.

You can do more crazy things with std::bind like changing order of arguments of a function.

Back to example

Let’s move back to our example. std::bind(std::plus<int>(),std::placeholders::_1, ELEM_TO_ADD) in our example binds std::plus functor, first argument passed to bind (which in our case would be elements of vector, passed one by one) and constant ELEM_TO_ADD. In short this line transforms binary functor std::plus into unary functor. Another argument of functor is fixed value ELEM_TO_ADD.

Finally, we are storing the result of functor in vector, vec2, by using stl function std::back_inserter. This function just uses push_back function of vector to insert result at back of specfied vector.

So, now you might be feeling that functors are indeed powerful. In next blog we will talk about lambdas, which are quite concise way of writing anonymous functions.

Till then Sayonara.

Exercise

Can you think of solution to re-order arguments of a functions and create a new function? Basically, we want to define func3 as

func3(arg1,arg2,arg3){
	func4(arg2,arg3,arg1);
}

If yes, let me know in comments how would you achieve this using std::bind

Thanks

Functors in C++ - Part I

What is a functor?

Functor or function object is a C++ class which defines the operator ( ). Functor let’s you create objects which “looks like” functions.

Consider below code to add two numbers:

#include<cassert>

struct MyAddFunctor {
	
	// Constructor
	MyAddFunctor(int inp){
		x = inp;
	}
	
	// Defining operator()
	int operator()(int y){
		return x+y;
	}
	
	int x;
};

int main(){
	MyAddFunctor func(5);
	int ret = func(10);
	//ret would be 15.
	assert(ret == 15);
	
	int ret2 = func(25);
	// ret would br 30
	assert(ret2 == 30);
}

Now MyAddFunctor is a functor. It is a functor because MyAddFunctor is C++ class which implemented operator().

How are functors called?

We call functors just like regular C++ class. Unlike functions we first need to create object of functor like MyAddFunctor func(5). We are passing 5 as argument only becase we have a constructor defined in MyAddFunctor class which takes int as an argument.

Now when object of functor class is created we invoke the function using () operator just like func(10).

We could also combine instantiation and invocation in single statement as MyAddFunctor(5)(10).

Why are they called as Function Objects?

The reason why they are called as function objects is because we can call class MyAddFunctor as if it is a function. Example : func(10).

Why are functors used?

The main advantage of using functor is that they store state. Consider our previous example of MyAddFunctor. In that example we stored value of x in the class and so we didn’t need to pass x in each call.

One can argue that the work done by MyAddFunctor can simply be done by writing C++ function as below:

int addFunction(int x){
	return 5+x;
}

But in addFunction we are hardcoding the value 5 and in functor we are not doing so. So MyAddFunctor is more customizable.

Functors are often used in STL. We will talk about functors more in next blog post. Till then stay tuned and let me know your comments on this post.

Thanks

Line by Line profiling of C++ code

Recently I encountered a performance issue in C++ code. I wrote around 200 lines of C++ code which was working perfectly fine with small input but damm slow with large input. I decided to profile the C++ code using gprofile. As a newbie to profiling market I searched a lot but was not able to find step by step instructions on how to profile C++ code line be line. And so I decided to document the steps I followed in this blog post.

There are many profilers available in market but after reading a lot about them I decide to go with gprof. To keep the post short and to the point I won’t describe logic behind each step.

Step 1. For check whether gprof is installed on your system.To do this, just run below command in terminal grpof

    If you get an error then follow below step to install it. Else, move to next step 

    For debian install using command 
        `apt-get install binutils`

    For Mac Os using command (assuming you have homebrew installed)
        `brew install binutils`

Step 2. Compile your C++ code with -pg -g flag. Something like: g++ -pg -g -o final final.cpp

TensorFlow - Exercise 3 - Counting

Exercise : Counting

Count upto 5 in tensorflow

Expected Output 1 2 3 4 5

Caution : Solution for exercise is below. Please try solving problem by yourself before looking below

import tensorflow as tf

# Initialize count with value 0
count = tf.Variable(0)

newVal = tf.add(count,1)
# Assign operation updates the value of ref
# https://www.tensorflow.org/api_docs/python/tf/assign
assignment = tf.assign(count,newVal)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    # Now update the count 5 times
    for count in range(5):
        print(sess.run(assignment))
1
2
3
4
5

Threadpool in C++

What is a ThreadPool

A thread pool is a pool of initialized threads which are ready to take workload. Thread pool is preferred over conventional thread system when we have large number of small task to be done.

Working

When ThreadPool class is initialized then few number of threads are created (we may even create zero threads initially, as done in my implementation) and these newly created threads are made to wait on condition variable.

Now when we want a thread from our threadpool to run a new job we follow below steps:

  1. Check if there is any free thread in our ThreadPool. Free thread means thread which is waiting on condition variable.
  2. If there is atleast one free available then choose one free thread from pool and jump to step 5. Else continue.
  3. Create few more threads like 5, 10 or so and make these new threads wait on condition variable too.
  4. Now select one free thread from newly created threadpool.
  5. Wake the selected thread by signalling on condition variable and give the workload to this selected thread.
  6. When the workload is finished then make the thread wait on condition variable again.

In threadpool we never destroy any thread until destructor of ThreadPool class is called.

API

Following methods are available in the API:

Signature Parameters Return Description
ThreadPool::ThreadPool() None None Constructor. Creates zero threads and initializes all the required members of ThreadPool class.
ThreadPool::~ThreadPool() None None Destructor. Destructs ThreadPool class.
int ThreadPool_run(struct ThreadPool tp, struct ThreadID threadId, void* (*run)(void *), void * args) struct ThreadPool* : ThreadPool Id returned by ThreadPool constructor. void* (run)(void *) : Workload. Callback function which selected thread should run. void : Arguments to be passed to callback function. 0 on Success and 1 on failure Workload is send to ThreadPool using this function.
int ThreadPool_join(struct ThreadID thdid, void **ret) struct ThreadID : ThreadId as reutrned by ThreadPool_run. void** : Return value of callback function for a given ThreadID is returned back. 0 on Success,and 1 on failure This function blocks the calling thread till ThreadId passed in argument is busy with some workload and function returns when workload is completed. In case given ThreadId is not running any workload then this function returns immediately.

Implementation

Can be found here.

Hope you found this post useful. Please comment in case of any query.

Thanks