Fast and general use of lambda functions

Motivation

I created a header file that wraps the functionality of Matlab mex in the C ++ 11 classes; especially for MxNxC images. Two functions that I created are forEach, which iterates over each pixel of the image, and forKernel, which sets the core and the pixel in the image, iterates around the core around this pixel, processing all kinds of elegant mathematical data for indexing the boiler plate.

The idea is that you can program sliding windows as follows:

image.forEach([](Image &image, size_t row, size_t col) {
  //kr and lc specify which pixel is the center of the kernel
  image.forKernel<double>(row, col, kernel, kr, kc, [](Image &image, double w, size_t row, size_t col) {
    // w is the weight/coefficient of the kernel, row/col are the corresponding coordinates in the image.
    // process ...
  });
});

Problem

This provides a good way.

  • increase readability: two function calls are much clearer than the corresponding 4-loop to do the same,
  • : - , forEach/forKernel
  • , : 8 , .

, , . , g++ lambda- . . 1D:

#include <iostream>
#include <functional>

struct Data {
  size_t d_size;
  double *d_data;
  Data(size_t size) : d_size(size), d_data(new double[size]) {}
  ~Data() { delete[] d_data; }
  double &operator[](size_t i) { return d_data[i]; }


  inline void forEach(std::function<void(Data &, size_t)> f) {
    for (size_t index = 0; index != d_size; ++index)
      f(*this, index);
  }
};



int main() {
  Data im(50000000);
  im.forEach([](Data &im, size_t i) {
    im[i] = static_cast<double>(i);
  });

  double sum = 0;
  im.forEach([&sum](Data &im, size_t i) {
    sum += im[i];
  });

  std::cout << sum << '\n';
}

: http://ideone.com/hviTwx

, forEach -, . , -, , .

, , , (double, int,...), " " .

:

#include <iostream>
#include <functional>

struct Data {
  size_t d_size;
  double *d_data;
  Data(size_t size) : d_size(size), d_data(new double[size]) {}
  ~Data() { delete[] d_data; }
  double &operator[](size_t i) { return d_data[i]; }
};



int main() {
  size_t len = 50000000;
  Data im(len);
  for (size_t index = 0; index != len; ++index)
    im[index] = static_cast<double>(index);

  double sum = 0;
  for (size_t index = 0; index != len; ++index)
    sum += im[index];

  std::cout << sum << '\n';
}

: http://ideone.com/UajMMz

8 , , , .

- , forEach -? - - , , , ?

:

, -. : - Data.forEach , / ( , , ).

forEveR

, , 2x :

:

herbert@machine ~ $ g++ -std=c++11 -Wall test0.cc -o test0
herbert@machine ~ $ g++ -std=c++11 -Wall test1.cc -o test1
herbert@machine ~ $ g++ -std=c++11 -Wall test2.cc -o test2
herbert@machine ~ $ time ./test0
1.25e+15

real    0m2.563s
user    0m2.541s
sys     0m0.024s
herbert@machine ~ $ time ./test1
1.25e+15

real    0m0.346s
user    0m0.320s
sys     0m0.026s
herbert@machine ~ $ time ./test2
1.25e+15

real    0m0.601s
user    0m0.575s
sys     0m0.026s
herbert@machine ~ $ 

-O2, . test1 test2 ar . @stijn @forEveR.

herbert@machine ~ $ g++ -std=c++11 -Wall -O2 test0.cc -o test0
herbert@machine ~ $ g++ -std=c++11 -Wall -O2 test1.cc -o test1
herbert@machine ~ $ g++ -std=c++11 -Wall -O2 test2.cc -o test2

herbert@machine ~ $ time ./test0
1.25e+15

real    0m0.256s
user    0m0.229s
sys 0m0.028s
herbert@machine ~ $ time ./test1
1.25e+15

real    0m0.111s
user    0m0.078s
sys 0m0.033s
herbert@machine ~ $ time ./test2
1.25e+15

real    0m0.108s
user    0m0.076s
sys 0m0.032s
herbert@machine ~ $ 
+4
1

, std::function, type-erasure . std::function. - , - n3376 5.1.2/5

- (13.5.4), ---- trailing-return-type

,

  template<typename Function>
  inline void forEach(Function f) {
    for (size_t index = 0; index != d_size; ++index)
      f(*this, index);
  }

+6

All Articles