Parallel Manual

About

The static classes maxon::ParallelFor, maxon::ParallelImage and maxon::ParallelInvoke are used to execute parallelized code.

ParallelFor

The maxon::ParallelFor class is used to execute code defined in a worker method. This code is executed in a loop distributed over multiple threads. The workload is distributed either dynamically or statically.

// This example calculates an approximation of PI using random numbers.
// array that stores the inside/outside state for each generated point
// ParallelFor will write into this array from multiple threads simultaneously
pointStates.Resize(count) iferr_return;
auto worker = [&pointStates](maxon::Int i)
{
pointStates[i] = false;
// create random point
random.Init(maxon::UInt32(i));
point.x = random.Get01();
point.y = random.Get01();
// check if inside circle
if (point.GetSquaredLength() < 1.0)
pointStates[i] = true;
};
// generate and check random points
maxon::ParallelFor::Dynamic(0, count, worker);
// get pi
maxon::Int64 insideCount = 0;
for (const maxon::Bool pointInside : pointStates)
{
if (pointInside)
insideCount++;
}
const maxon::Float pi = 4.0 * maxon::Float(insideCount) / maxon::Float(count);
DiagnosticOutput("PI approximation: @", pi);

maxon::ParallelFor::BreakContext is a base class to define a context for maxon::ParallelFor loops that support cancellation. A class based on maxon::ParallelFor::BreakContext stores the data handled in a thread.

maxon::ParallelFor can call additional "Init" and "Finalize" functions for each thread. The behaviour is defined with these flags:

// This example calculates an approximation of PI using random numbers.
// total number inside the unit-circle
maxon::Int insideCount = 0;
// data structure
struct LocalData : public maxon::ParallelFor::BreakContext
{
maxon::Int localCount; // number of points inside the unit-circle
};
// init thread (called threaded)
auto init = [](LocalData& context)
{
context.localCount = 0;
};
// worker
auto worker = [](maxon::Int i, LocalData& context)
{
random.Init(maxon::UInt32(i));
point.x = random.Get01();
point.y = random.Get01();
if (point.GetSquaredLength() < 1.0)
context.localCount++;
};
// finalize thread (called synchronously)
auto finalize = [&insideCount](LocalData& context)
{
// get total number of points inside the unit-circle
insideCount += context.localCount;
};
// run parallel code
maxon::ParallelFor::Dynamic<LocalData, maxon::PARALLELFORFLAGS::INITTHREADED_FINALIZESYNC>(0, count, init, worker, finalize) iferr_return;
// get pi
const maxon::Float pi = 4.0 * maxon::Float(insideCount) / maxon::Float(count);
DiagnosticOutput("PI approximation: @", pi);

ParallelImage

maxon::ParallelImage is a special class to process image data of a given size per pixel.

// This example fills a BaseBitmap with an UV color gradient.
// allocate bitmap
if (bitmap == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
// define bitmap size
const maxon::Int width = 1024;
const maxon::Int height = 1024;
const IMAGERESULT res = bitmap->Init(width, height, 24);
if (res != IMAGERESULT::OK)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
// dimensions as float values
const maxon::Float widthF = maxon::Float(width);
const maxon::Float heightF = maxon::Float(height);
auto worker = [widthF, heightF, &bitmap](maxon::Int x, maxon::Int y)
{
// get UV coords for the given pixel
const maxon::Float xf = maxon::Float(x);
const maxon::Float yf = maxon::Float(y);
const maxon::Float u = xf / widthF;
const maxon::Float v = yf / heightF;
// set colors based on UV coords
const maxon::Int32 red = maxon::SafeConvert<maxon::Int32>(u * 255.9);
const maxon::Int32 green = maxon::SafeConvert<maxon::Int32>(v * 255.9);
const maxon::Int32 blue = 0;
// store color in the bitmap
bitmap->SetPixel(Int32(x), Int32(y), red, green, blue);
};
// process every pixel of the given bitmap
maxon::ParallelImage::Process(width, height, 30, worker);
ShowBitmap(bitmap);

ParallelInvoke

The maxon::ParallelInvoke function can be used to execute multiple arbitrary functions in parallel.

// This example uses ParallelInvoke() to search for
// min/max values in two given arrays in parallel.
// min/max values
maxon::Float minA = 0.0, maxA = 0.0, minB = 0.0, maxB = 0.0;
// search for min/max values in the given arrays
// GetMinMax() is a custom function
[&arrayA, &minA, &maxA] { GetMinMax(arrayA, minA, maxA); },
[&araryB, &minB, &maxB] { GetMinMax(araryB, minB, maxB); }
// check min/max values
if ((minA > minB) && (maxA < maxB))
DiagnosticOutput("Min/max values of a array A are within the min/max values of array B"_s);

Further Reading

IMAGERESULT::OK
@ OK
Image loaded/created.
maxon::ParallelImage::Process
static void Process(Int width, Int height, Int tileSize, const WORKER &worker)
Definition: parallelimage.h:216
maxon::Vec2::y
T y
Definition: vec2.h:32
maxon::Int64
int64_t Int64
64 bit signed integer datatype.
Definition: apibase.h:174
maxon::BaseArray::Resize
ResultMem Resize(Int newCnt, COLLECTION_RESIZE_FLAGS resizeFlags=COLLECTION_RESIZE_FLAGS::DEFAULT)
Definition: basearray.h:1077
maxon::Bool
bool Bool
boolean type, possible values are only false/true, 8 bit
Definition: apibase.h:177
iferr_return
#define iferr_return
Definition: resultbase.h:1434
maxon::Vec2::x
T x
Definition: vec2.h:31
MAXON_SOURCE_LOCATION
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:66
maxon::Float
Float64 Float
Definition: apibase.h:193
maxon::BaseArray
Definition: basearray.h:368
BaseBitmap::Init
static IMAGERESULT Init(BaseBitmap *&res, const Filename &name, Int32 frame=-1, Bool *ismovie=nullptr, BitmapLoaderPlugin **loaderplugin=nullptr, const maxon::Delegate< void(Float progress)> &progressCallback=nullptr)
DiagnosticOutput
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:166
maxon::ParallelFor::Dynamic
static auto Dynamic(FROMTYPE from, INDEXTYPE to, const LOOP &obj, Int threadCnt=PARALLELFOR_USEMAXIMUMTHREADS, const Int granularity=PARALLELFOR_DEFAULTGRANULARITY, JobQueueInterface *queue=JOBQUEUE_CURRENT) -> decltype(obj(to))
Definition: parallelfor.h:238
maxon::Int32
int32_t Int32
32 bit signed integer datatype.
Definition: apibase.h:172
BaseBitmap::SetPixel
Bool SetPixel(Int32 x, Int32 y, Int32 r, Int32 g, Int32 b)
Definition: c4d_basebitmap.h:704
maxon::Int
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:184
maxon::UInt32
uint32_t UInt32
32 bit unsigned integer datatype.
Definition: apibase.h:173
maxon::LinearCongruentialRandom
Definition: lib_math.h:19
maxon::LinearCongruentialRandom::Init
void Init(UInt32 seed)
maxon::Vec2
A vector consisting of three components X, Y and Z.
Definition: vec2.h:16
Int32
maxon::Int32 Int32
Definition: ge_sys_math.h:58
ShowBitmap
Bool ShowBitmap(const Filename &fn)
maxon::Vec2::GetSquaredLength
constexpr T GetSquaredLength() const
Returns the squared length of the vector.
Definition: vec2.h:388
AutoAlloc
Definition: ge_autoptr.h:37
IMAGERESULT
IMAGERESULT
Definition: ge_prepass.h:3660
maxon::ParallelFor::BreakContext
Context for ParallelFor loops that support cancellation.
Definition: parallelfor.h:189
maxon::LinearCongruentialRandom::Get01
FLOAT Get01()
Returns the next random value in the range of [0..1].
maxon::ParallelInvoke
Result< void > ParallelInvoke(Bool parallel, ARGS &&... args)
Definition: parallelinvoke.h:153