Skip to content
Martin Hartl edited this page Dec 12, 2017 · 7 revisions

allscale::api::user::algorithm::pfor

Defined in header "allscale/api/user/algorithm/pfor.h"

The pfor operator iterates over a given iterator range and applies a given function (loop body) to the elements of this range in parallel.

Signatures

Multiple signatures are offered for the pfor operator:

using namespace allscale::api::user::algorithm;


template<typename Iter, typename Body, typename Dependency>
detail::loop_reference<Iter> pfor(const detail::range<Iter>& r,
                                  const Body& body,
                                  const Dependency& dependency 
                                  );
template<typename Iter, typename Body>
detail::loop_reference<Iter> pfor(const detail::range<Iter>& r,
                                  const Body& body, 
                                  const no_dependencies& = no_dependencies()
                                  );
template<typename Iter, size_t dims, typename Body>
detail::loop_reference<std::array<Iter,dims>> pfor(const std::array<Iter,dims>& a, 
                                                   const std::array<Iter,dims>& b, 
                                                   const Body& body
                                                   );
template<typename Iter, size_t dims, typename Body, typename Dependency>
detail::loop_reference<std::array<Iter,dims>> pfor(const std::array<Iter,dims>& a, 
                                                   const std::array<Iter,dims>& b, 
                                                   const Body& body, 
                                                   const Dependency& dependency
                                                   );
template<typename Iter, typename Body, typename Dependency>
detail::loop_reference<Iter> pfor(const Iter& a, 
                                  const Iter& b, 
                                  const Body& body, 
                                  const Dependency& dependency
                                  );
template<typename Iter, typename Body>
detail::loop_reference<Iter> pfor(const Iter& a, 
                                  const Iter& b, 
                                  const Body& body
                                  );
template<typename Container, typename Op>
detail::loop_reference<typename Container::iterator> pfor(Container& c,
                                                          const Op& op
                                                          );
template<typename Container, typename Op, typename Dependency>
std::enable_if_t<detail::is_loop_dependency<Dependency>::value,detail::loop_reference<typename Container::iterator>>
pfor(Container& c, 
     const Op& op, 
     const Dependency& dependency
     );
template<typename Container, typename Op>
detail::loop_reference<typename Container::const_iterator> pfor(const Container& c,
                                                                const Op& op
                                                                );
template<typename Container, typename Op, typename Dependency>
detail::loop_reference<typename Container::const_iterator> pfor(const Container& c,
                                                                const Op& op, 
                                                                const Dependency& dependency
                                                                );
template<typename Elem, size_t dims, typename Body>
detail::loop_reference<utils::Vector<Elem,dims>> pfor(const utils::Vector<Elem,dims>& a,
                                                      const utils::Vector<Elem,dims>& b,
                                                      const Body& body
                                                      );
template<typename Elem, size_t dims, typename Body, typename Dependencies>
detail::loop_reference<utils::Vector<Elem,dims>> pfor(const utils::Vector<Elem,dims>& a, 
                                                      const utils::Vector<Elem,dims>& b, 
                                                      const Body& body, 
                                                      const Dependencies& dependencies
                                                      );
template<typename Elem, size_t Dims, typename Body>
detail::loop_reference<utils::Vector<Elem,dims>> pfor(const utils::Vector<Elem,Dims>& a, 
                                                      const Body& body
                                                      );
template<typename Elem, size_t Dims, typename Body, typename Dependencies>
detail::loop_reference<utils::Vector<Elem,dims>> pfor(const utils::Vector<Elem,Dims>& a, 
                                                      const Body& body, 
                                                      const Dependencies& dependencies
                                                      );

Examples

Ranges

Iterating Over a One-dimensional Array

#include <array>
#include <allscale/api/user/algorithm/pfor.h>

using namespace allscale::api::user::algorithm;

const int N = 200;

// increment each element by one
void increment(std::array<int,N>& data) {
  pfor(0,N,[&](int i) {
    data[i]++;
  });
}

Iterating Over a Multi-dimensional Grid

#include <allscale/api/user/data/grid.h>
#include <allscale/api/user/algorithm/pfor.h>

using namespace allscale::api::user;
using namespace allscale::api::user::algorithm;

using Grid = data::Grid<int, 3>;
using GridPoint = Grid::coordinate_type;

const GridPoint N = { 200, 300, 400 };

// increment each element by one
void increment(Grid& data) {
  const GridPoint zero = { 0, 0, 0};
  pfor(zero,N,[&](GridPoint pos) {
    data[pos]++;
  });
}

Synchronization

Global Synchronization

#include <array>
#include <allscale/api/user/algorithm/pfor.h>

using namespace allscale::api::user::algorithm;

const int N = 200;

// increment each element by one
void initAndIncrement(std::array<int,N>& data) {
  pfor(0,N,[&](int i) {
    data[i] = 1;
  });
  // second pfor will execute after every iteration of the first pfor completed
  pfor(0,N,[&](int i) {
    data[i]++;
  });
}

Fine-Grained Synchronization - One-On-One

#include <array>
#include <allscale/api/user/algorithm/pfor.h>

using namespace allscale::api::user::algorithm;

const int N = 200;

// increment each element by one
void initAndIncrement(std::array<int,N>& data) {
  auto ref = pfor(0,N,[&](int i) {
    data[i] = 1;
  });
  // second pfor will execute iteration i after first pfor has finished iteration i
  pfor(0,N,[&](int i) {
    data[i]++;
  }, one_on_one(ref));
}

Fine-Grained Synchronization - Neighborhood

#include <array>
#include <allscale/api/user/algorithm/pfor.h>

using namespace allscale::api::user::algorithm;

const int N = 200;

// increment each element by one
void initAndIncrement(const std::array<int,N>& data, std::array<int,N>& output) {
  auto ref = pfor(0,N,[&](int i) {
    output[i] = 0;
  });
  // second pfor will execute iteration i after first pfor has finished iterations i-1, i and i+1
  pfor(1,N-1,[&](int i) {
    output[i] += data[i+1] + data[i] + data[i-1];
  }, neighborhood_sync(ref));
}

Clone this wiki locally