The arbb::call() and arbb::map() functions are used to call user-defined functions in a way that optimizes them through the Intel(R) Array Building Blocks (Intel(R) ArBB).
Functions passed to arbb::call() and arbb::map() must have the following properties:
void
.const
) references of such types.Violating these requirements results in a compilation failure or an exception being thrown (see Exceptions).
The arbb::call() function takes a single pointer to a C++ function and returns an arbb::closure object. The returned arbb::closure object can in turn be called with parameters matching those of the C++ function. In the process of creating the arbb::closure, Intel(R) ArBB optimizes and compiles operations on ArBB types (see Scalars and Containers) into native code for any architecture supported by ArBB.
As this compilation process occurs at runtime, the arbb::call() function only performs it once for any given C++ function. Subsequent calls to arbb::call() with the same function return the same arbb::closure as the first call, without any compilation overhead.
The following code example shows how you can use arbb::call():
#include <iostream> #include <arbb.hpp> // You may pass this function to arbb::call(), because it returns // void, takes fewer than 35 parameters (three), and the parameters // are all of Intel(R) ArBB types, or references thereof. void blend_in(arbb::dense<arbb::f32>& a, arbb::f32 factor, arbb::dense<arbb::f32> b) { a += factor * b; } int main() { // Create some arbitrary sample data. arbb::dense<arbb::f32> base = arbb::fill(0.0f, 1024); arbb::dense<arbb::f32> addition = arbb::fill(10.0f, 1024); f32 factor = 0.1f; // Apply the function a few times. for (int i = 0; i < 4; ++i) { // The first iteration of this loop, when i == 0, causes a // compilation. Subsequent iterations reuse the compilation. arbb::call(blend_in)(base, factor, addition); } // Output the resulting values. arbb::range<arbb::f32> base_data = base.read_only_range(); for (std::size_t j = 0; j < 1024; ++j) { std::cout << base_data[j] << std::endl; } }
The arbb::call() function uses the closure capture mechanism to obtain an arbb::closure the first time it encounters a given function. You can find details on how closure capture works in the Closures section.
For closure capture to work correctly, the computations to be applied by Intel(R) ArBB when running a function must be expressed using Intel(R) ArBB types and operations. Computations expressed using regular C++ types, such as adding two float
variables together, can still be performed, but only their results, not the computations themselves, will be stored in the resulting closure during the first call to arbb::call().
Functions passed to arbb::call() may call other functions, either directly or using arbb::call(). Direct function calls are always inlined, effectively making the function call itself invisible to the Intel(R) ArBB compilation process. Calls using arbb::call() are recognized by Intel(R) ArBB and either compiled into function calls in native code or inlined.
The arbb::map() function works very similarly to arbb::call() and has the same basic restrictions, but its return value allows arguments to a call to be containers (see Dense Containers) even when the corresponding parameter types of the function are elements of those containers.
In addition to the restrictions common to the arbb::call() and arbb::map() functions, arbb::map() imposes the following constraints on the function being passed in, the context in which arbb::map() is invoked, and the arguments passed to objects returned by arbb::map():
const
qualifiers stripped).Violating these requirements results in a compilation failure or an exception being thrown (see Exceptions).
In a call to an object returned by arbb::map(), fixed arguments are arguments whose type exactly matches those of the parameters to which they are being passed. Varying arguments are containers being passed to parameters corresponding to their element type.
The following code example illustrates the use of arbb::map():
#include <iostream> #include <arbb.hpp> // You may pass this function to arbb::map(), because it returns // void, takes fewer than 35 parameters (three), and the parameters // are all of Intel(R) ArBB types, or references thereof. // It also does not contain any arbb::map() or arbb::call() // invocations, or declare any local containers, and has a // non-container parameter (a) declared as a reference. void blend_in_scalar(arbb::f32& a, arbb::f32 factor, arbb::f32 b) { a += factor * b; } // As arbb::map() can only occur within a function passed to // arbb::call(), and not within functions such as arbb::main(), // this function is written to perform the actual arbb::map(). void blend_in(arbb::dense<f32>& a, f32 factor, arbb::dense<f32> b) { // This applies blend_in_scalar to all elements of a and b // (which are thus varying arguments), with the same value of // factor corresponding to all elements (a fixed argument). arbb::map(blend_in_scalar)(a, factor, b); } int main() { // Create some arbitrary sample data arbb::dense<arbb::f32> base = arbb::fill(0.0f, 1024); arbb::dense<arbb::f32> addition = arbb::fill(10.0f, 1024); f32 factor = 0.1f; // Apply the function a few times. for (int i = 0; i < 4; ++i) { arbb::call(blend_in)(base, factor, addition); } // Output the resulting values arbb::range<arbb::f32> base_data = base.read_only_range(); for (std::size_t j = 0; j < 1024; ++j) { std::cout << base_data[j] << std::endl; } }
If all arguments being passed in are fixed arguments (in other words, if there are no containers being passed to non-container parameters), such a call behaves exactly as a call to arbb::call() would have.
Otherwise, the function is invoked in as many instances as there are elements in one of the varying arguments. Due to the restrictions on functions passed to arbb::map() and their invocations, all varying arguments have the same dimensionality and size. Each instance of the invocation has a unique corresponding index into these containers. For each instance, the function is executed with the container elements at these indices from the varying arguments passed to the corresponding parameters. Fixed arguments are passed directly to their corresponding parameters, and remain the same for all instances.
Instances are completely independent from one another. This allows them to be executed in arbitrary order and in parallel without affecting the result.
The arbb::position() and arbb::neighbor() functions have special meaning when used in functions passed to arbb::map().
The arbb::position() function returns the current position, which is the index from which elements are read from varying arguments by default. It has several overloads, but they all perform the same basic functionality, and differ only in the number values they return, and the mechanism by which the value is returned.
If an invocation of arbb::position() returns a value along a dimension beyond the dimensionality of the varying arguments, a zero value is returned corresponding to that dimension.
You can use the arbb::neighbor() function to read the elements of varying arguments at indices offset from the current position by a given amount. As with arbb::position(), they differ only in the number of dimensions along which the offset is specified, and the way in which that offset is specified. Calling overloads of neighbor() that do not take a parameter for a given dimension is equivalent to calling overloads taking such a parameter with a zero value passed as the argument.
The arbb::neighbor() function does not allow reading the outputs of other arbb::map() invocation instances, because it always returns the element as it was before the function began executing. This allows such invocations to execute in parallel, because they remain independent.
The arbb::position() function can be called without being inside of a function passed to arbb::map(). In that case, it always returns values equal to zero.
The arbb::neighbor() function can be called without being inside of a function passed to arbb::map() as well. In this case, or when called on a value that is not an input to such a function, it simply returns the value passed in.
Functions | |
template<typename FunctionType > | |
closure< FunctionType > | arbb::call (FunctionType function) |
Returns an arbb::closure corresponding to function that can be used to perform the computations expressed in function . | |
template<typename FunctionType > | |
unspecified_type< FunctionType > | arbb::map (FunctionType function) |
Returns an object corresponding to function that can be used to perform the computations expressed in function as a map invocation. | |
template<typename T , std::size_t D> | |
detail::disable_if < detail::is_container< T > ::value, T >::type | arbb::neighbor (const T &source, const array< isize, D > &offset) |
Returns the element from the container corresponding to source in an arbb::map() invocation at the given offset from the current position. | |
template<typename T > | |
detail::disable_if < detail::is_container< T > ::value, T >::type | arbb::neighbor (const T &source, const isize &col) |
Returns the element from the container corresponding to source in an arbb::map() invocation at the an offset of {col, 0, 0} from the current position. | |
template<typename T > | |
detail::disable_if < detail::is_container< T > ::value, T >::type | arbb::neighbor (const T &source, const isize &col, const isize &row) |
Returns the element from the container corresponding to source in an arbb::map() invocation at the an offset of {col, row, 0} from the current position. | |
template<typename T > | |
detail::disable_if < detail::is_container< T > ::value, T >::type | arbb::neighbor (const T &source, const isize &col, const isize &row, const isize &page) |
Return the element from the container corresponding to source in an arbb::map() invocation at the an offset of {col, row, page} from the current position. | |
void | arbb::position (usize &col) |
Returns the current position along the first dimension of an arbb::map() invocation into col . | |
void | arbb::position (usize &col, usize &row) |
Returns the current position along the first and second dimension of an arbb::map() invocation into {col, row} . | |
void | arbb::position (usize &col, usize &row, usize &page) |
Returns the current position along all dimensions of an arbb::map() invocation into {col, row, page} . | |
template<std::size_t D> | |
void | arbb::position (array< usize, D > &pos) |
Returns the current position along the first D dimensions of an arbb::map() invocation into pos . | |
template<std::size_t D> | |
array< usize, D > | arbb::position () |
Returns the current position along the first D dimensions of an arbb::map() invocation as an arbb::array<usize, D> object. |
closure<FunctionType> arbb::call | ( | FunctionType | function | ) | [inline] |
Returns an arbb::closure corresponding to function
that can be used to perform the computations expressed in function
.
See Function Invocation for details.
The first invocation of arbb::call() with a given value of function
is equivalent to arbb::capture(function)
. Subsequent invocations of arbb::call() with the same value of function
return the closure captured during the first invocation.
FunctionType | The type of the function being passed. See Function Invocation for details on permitted function types. |
unspecified_type<FunctionType> arbb::map | ( | FunctionType | function | ) | [inline] |
Returns an object corresponding to function
that can be used to perform the computations expressed in function
as a map invocation.
arbb::map() may only be called from within a function passed to arbb::call(). See Function Invocation for details.
FunctionType | The type of the function being passed. See Function Invocation for details on permitted function types. |
detail::disable_if<detail::is_container<T>::value, T>::type arbb::neighbor | ( | const T & | source, | |
const array< isize, D > & | offset | |||
) | [inline] |
Returns the element from the container corresponding to source
in an arbb::map() invocation at the given offset
from the current position.
See Function Invocation for details.
detail::disable_if<detail::is_container<T>::value, T>::type arbb::neighbor | ( | const T & | source, | |
const isize & | col | |||
) | [inline] |
Returns the element from the container corresponding to source
in an arbb::map() invocation at the an offset of {col, 0, 0}
from the current position.
See Function Invocation for details.
detail::disable_if<detail::is_container<T>::value, T>::type arbb::neighbor | ( | const T & | source, | |
const isize & | col, | |||
const isize & | row | |||
) | [inline] |
Returns the element from the container corresponding to source
in an arbb::map() invocation at the an offset of {col, row, 0}
from the current position.
See Function Invocation for details.
detail::disable_if<detail::is_container<T>::value, T>::type arbb::neighbor | ( | const T & | source, | |
const isize & | col, | |||
const isize & | row, | |||
const isize & | page | |||
) | [inline] |
Return the element from the container corresponding to source
in an arbb::map() invocation at the an offset of {col, row, page}
from the current position.
See Function Invocation for details.
void arbb::position | ( | usize & | col | ) |
Returns the current position along the first dimension of an arbb::map() invocation into col
.
See Function Invocation for details.
void arbb::position | ( | usize & | col, | |
usize & | row | |||
) |
Returns the current position along the first and second dimension of an arbb::map() invocation into {col, row}
.
See Function Invocation for details.
void arbb::position | ( | usize & | col, | |
usize & | row, | |||
usize & | page | |||
) |
Returns the current position along all dimensions of an arbb::map() invocation into {col, row, page}
.
See Function Invocation for details.
void arbb::position | ( | array< usize, D > & | pos | ) | [inline] |
Returns the current position along the first D
dimensions of an arbb::map() invocation into pos
.
See Function Invocation for details.
array<usize, D> arbb::position | ( | ) | [inline] |
Returns the current position along the first D
dimensions of an arbb::map() invocation as an arbb::array<usize, D>
object.
See Function Invocation for details.
Copyright © 2010, Intel Corporation. All rights reserved.