Commit ef7f3f5a by Marcus Winter

tutorial, examples: added description of plugins

parent 3ed41486
...@@ -10,6 +10,9 @@ include_directories( ...@@ -10,6 +10,9 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../../base_cpp/include ${CMAKE_CURRENT_SOURCE_DIR}/../../base_cpp/include
${CMAKE_CURRENT_BINARY_DIR}/../../base_cpp/include ${CMAKE_CURRENT_BINARY_DIR}/../../base_cpp/include
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_c/include ${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_c/src
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_network_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_opencl_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_cpp/include ${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_cpp/include
${CMAKE_CURRENT_BINARY_DIR}/../../mtapi_cpp/include ${CMAKE_CURRENT_BINARY_DIR}/../../mtapi_cpp/include
${CMAKE_CURRENT_SOURCE_DIR}/../../containers_cpp/include ${CMAKE_CURRENT_SOURCE_DIR}/../../containers_cpp/include
...@@ -21,7 +24,13 @@ if(CMAKE_COMPILER_IS_GNUCXX) ...@@ -21,7 +24,13 @@ if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-std=c++11") set(CMAKE_CXX_FLAGS "-std=c++11")
endif() endif()
IF(MSVC)
set (NETWORK_LIBS ws2_32)
ENDIF()
add_executable(examples ${EXAMPLES_SOURCES}) add_executable(examples ${EXAMPLES_SOURCES})
target_link_libraries(examples embb_dataflow_cpp embb_algorithms_cpp embb_mtapi_cpp target_link_libraries(examples embb_dataflow_cpp embb_algorithms_cpp embb_mtapi_cpp
embb_mtapi_c embb_base_cpp embb_base_c embb_containers_cpp ${compiler_libs}) embb_mtapi_network_c embb_mtapi_opencl_c embb_mtapi_c
embb_base_cpp embb_base_c embb_containers_cpp
${NETWORK_LIBS} ${compiler_libs})
CopyBin(BIN examples DEST ${local_install_dir}) CopyBin(BIN examples DEST ${local_install_dir})
...@@ -25,8 +25,12 @@ ...@@ -25,8 +25,12 @@
*/ */
#include <iostream> #include <iostream>
#include <embb/base/c/thread.h>
void RunMTAPI_C(); void RunMTAPI_C();
void RunMTAPI_C_Plugin();
void RunMTAPI_C_Network();
void RunMTAPI_C_OpenCL();
void RunMTAPI_CPP(); void RunMTAPI_CPP();
void RunDataflowLinear(); void RunDataflowLinear();
void RunDataflowNonLinear(); void RunDataflowNonLinear();
...@@ -45,12 +49,26 @@ void RunQueueExamples(); ...@@ -45,12 +49,26 @@ void RunQueueExamples();
* Runs all examples and tests their correctness. * Runs all examples and tests their correctness.
*/ */
int main() { int main() {
embb_thread_set_max_count(1024);
std::cout << "Running examples ..." << std::endl; std::cout << "Running examples ..." << std::endl;
std::cout << "RunMTAPI_C() ..." << std::endl; std::cout << "RunMTAPI_C() ..." << std::endl;
RunMTAPI_C(); RunMTAPI_C();
std::cout << "RunMTAPI_C() ... done" << std::endl; std::cout << "RunMTAPI_C() ... done" << std::endl;
std::cout << "RunMTAPI_C_Plugin() ..." << std::endl;
RunMTAPI_C_Plugin();
std::cout << "RunMTAPI_C_Plugin() ... done" << std::endl;
std::cout << "RunMTAPI_C_Network() ..." << std::endl;
RunMTAPI_C_Network();
std::cout << "RunMTAPI_C_Network() ... done" << std::endl;
std::cout << "RunMTAPI_C_OpenCL() ..." << std::endl;
RunMTAPI_C_OpenCL();
std::cout << "RunMTAPI_C_OpenCL() ... done" << std::endl;
std::cout << "RunMTAPI_CPP() ..." << std::endl; std::cout << "RunMTAPI_CPP() ..." << std::endl;
RunMTAPI_CPP(); RunMTAPI_CPP();
std::cout << "RunMTAPI_CPP() ... done" << std::endl; std::cout << "RunMTAPI_CPP() ... done" << std::endl;
......
/*
* Copyright (c) 2014-2015, Siemens AG. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <embb/mtapi/c/mtapi.h>
#include "mtapi_network_c_header-snippet.h"
#include <embb/base/c/internal/unused.h>
#include "mtapi_check_status-snippet.h"
#define NETWORK_DOMAIN 1
#define NETWORK_LOCAL_NODE 3
#define NETWORK_LOCAL_JOB 3
#define NETWORK_REMOTE_NODE 3
#define NETWORK_REMOTE_JOB 4
#include "mtapi_network_c_action_function-snippet.h"
void RunMTAPI_C_Network() {
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_task_hndl_t task;
mtapi_action_hndl_t network_action, local_action;
const int kElements = 64;
float arguments[kElements * 2];
float results[kElements];
for (int ii = 0; ii < kElements; ii++) {
arguments[ii] = static_cast<float>(ii);
arguments[ii + kElements] = static_cast<float>(ii);
}
mtapi_initialize(
NETWORK_DOMAIN,
NETWORK_LOCAL_NODE,
MTAPI_DEFAULT_NODE_ATTRIBUTES,
MTAPI_NULL,
&status);
MTAPI_CHECK_STATUS(status);
#include "mtapi_network_c_plugin_initialize-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_network_c_remote_action_create-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_network_c_local_action_create-snippet.h"
MTAPI_CHECK_STATUS(status);
job = mtapi_job_get(NETWORK_LOCAL_JOB, NETWORK_DOMAIN, &status);
MTAPI_CHECK_STATUS(status);
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
arguments, kElements * 2 * sizeof(float),
results, kElements*sizeof(float),
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
MTAPI_CHECK_STATUS(status);
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
for (int ii = 0; ii < kElements; ii++) {
if (results[ii] != ii * 2 + 1) {
printf("result %d was expected to be %d but was %d.\n",
ii, ii * 2 + 1, results[ii]);
exit(MTAPI_ERR_UNKNOWN);
}
}
#include "mtapi_network_c_plugin_finalize-snippet.h"
MTAPI_CHECK_STATUS(status);
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
}
/*
* Copyright (c) 2014-2015, Siemens AG. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <embb/mtapi/c/mtapi.h>
#include "mtapi_opencl_c_header-snippet.h"
#include "mtapi_check_status-snippet.h"
#define OPENCL_DOMAIN 1
#define OPENCL_NODE 2
#define OPENCL_JOB 2
// OpenCL Kernel Function for element by element vector addition
#include "mtapi_opencl_c_kernel-snippet.h"
void RunMTAPI_C_OpenCL() {
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_task_hndl_t task;
mtapi_action_hndl_t action;
const int kElements = 64;
float arguments[kElements * 2];
float results[kElements];
for (int ii = 0; ii < kElements; ii++) {
arguments[ii] = static_cast<float>(ii);
arguments[ii + kElements] = static_cast<float>(ii);
}
mtapi_initialize(
OPENCL_DOMAIN,
OPENCL_NODE,
MTAPI_DEFAULT_NODE_ATTRIBUTES,
MTAPI_NULL,
&status);
MTAPI_CHECK_STATUS(status);
#include "mtapi_opencl_c_plugin_initialize-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_opencl_c_action_create-snippet.h"
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
job = mtapi_job_get(OPENCL_JOB, OPENCL_DOMAIN, &status);
MTAPI_CHECK_STATUS(status);
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
arguments, kElements * 2 * sizeof(float),
results, kElements*sizeof(float),
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
MTAPI_CHECK_STATUS(status);
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
for (int ii = 0; ii < kElements; ii++) {
if (results[ii] != ii * 2 + 1) {
printf("result %d was expected to be %d but was %d.\n",
ii, ii * 2 + 1, results[ii]);
exit(MTAPI_ERR_UNKNOWN);
}
}
#include "mtapi_opencl_c_plugin_finalize-snippet.h"
MTAPI_CHECK_STATUS(status);
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
}
/*
* Copyright (c) 2014-2015, Siemens AG. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <embb/mtapi/c/mtapi.h>
#include <embb/mtapi/c/mtapi_ext.h>
#include <embb_mtapi_task_t.h>
#include <embb_mtapi_action_t.h>
#include <embb_mtapi_node_t.h>
#include <mtapi_status_t.h>
#include <embb/base/c/memory_allocation.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/atomic.h>
#include <embb/base/c/internal/unused.h>
#define PLUGIN_DOMAIN_ID 1
#define PLUGIN_NODE_ID 1
#define PLUGIN_JOB_ID 1
#include "mtapi_check_status-snippet.h"
#include "mtapi_c_plugin_task_schedule-snippet.h"
#include "mtapi_c_plugin_task_start_cb-snippet.h"
#include "mtapi_c_plugin_task_cancel_cb-snippet.h"
#include "mtapi_c_plugin_action_finalize_cb-snippet.h"
void RunMTAPI_C_Plugin() {
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_action_hndl_t action;
mtapi_task_hndl_t task;
mtapi_initialize(
PLUGIN_DOMAIN_ID,
PLUGIN_NODE_ID,
MTAPI_DEFAULT_NODE_ATTRIBUTES,
MTAPI_NULL,
&status);
MTAPI_CHECK_STATUS(status);
#include "mtapi_c_plugin_action_create-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_c_plugin_get_job-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_c_plugin_task_start-snippet.h"
MTAPI_CHECK_STATUS(status);
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
}
action = mtapi_ext_plugin_action_create(
PLUGIN_JOB_ID,
plugin_task_start,
plugin_task_cancel,
plugin_action_finalize,
MTAPI_NULL,
MTAPI_NULL,
0,
MTAPI_DEFAULT_ACTION_ATTRIBUTES,
&status);
void plugin_action_finalize(
MTAPI_IN mtapi_action_hndl_t action,
MTAPI_OUT mtapi_status_t* status
) {
EMBB_UNUSED(action);
// nothing to do for tearing down the plugin action
mtapi_status_set(status, MTAPI_SUCCESS);
}
job = mtapi_job_get(
PLUGIN_JOB_ID,
PLUGIN_DOMAIN_ID,
&status);
void plugin_task_cancel(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status
) {
EMBB_UNUSED(task);
// nothing to cancel in this simple example
mtapi_status_set(status, MTAPI_SUCCESS);
}
void plugin_task_schedule(embb_mtapi_task_t* local_task) {
// here the task might be dispatched to some hardware or separate thread
// mark the task as running
embb_mtapi_task_set_state(local_task, MTAPI_TASK_RUNNING);
// nothing to do to execute the no-op task
// just mark the task as done
embb_mtapi_task_set_state(local_task, MTAPI_TASK_COMPLETED);
}
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
MTAPI_NULL, 0,
MTAPI_NULL, 0,
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
void plugin_task_start(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status) {
mtapi_status_t local_status = MTAPI_ERR_UNKNOWN;
// do we have a node?
if (embb_mtapi_node_is_initialized()) {
// get the node instance
embb_mtapi_node_t * node = embb_mtapi_node_get_instance();
// is this a valid task?
if (embb_mtapi_task_pool_is_handle_valid(node->task_pool, task)) {
// get the tasks storage
embb_mtapi_task_t * local_task =
embb_mtapi_task_pool_get_storage_for_handle(node->task_pool, task);
// dispatch the task
plugin_task_schedule(local_task);
local_status = MTAPI_SUCCESS;
}
else {
local_status = MTAPI_ERR_TASK_INVALID;
}
}
else {
local_status = MTAPI_ERR_NODE_NOTINIT;
}
mtapi_status_set(status, local_status);
}
static void AddVectorAction(
void const * arguments,
mtapi_size_t arguments_size,
void * result_buffer,
mtapi_size_t result_buffer_size,
void const * node_local_data,
mtapi_size_t node_local_data_size,
mtapi_task_context_t * context) {
EMBB_UNUSED(context);
EMBB_UNUSED(result_buffer_size);
EMBB_UNUSED(node_local_data_size);
int elements = static_cast<int>(arguments_size / sizeof(float) / 2);
float const * a = reinterpret_cast<float const *>(arguments);
float const * b = reinterpret_cast<float const *>(arguments)+elements;
float * c = reinterpret_cast<float*>(result_buffer);
float const * d = reinterpret_cast<float const *>(node_local_data);
for (int ii = 0; ii < elements; ii++) {
c[ii] = a[ii] + b[ii] + d[0];
}
}
#include <embb/mtapi/c/mtapi_network.h>
network_action = mtapi_network_action_create(
NETWORK_DOMAIN,
NETWORK_LOCAL_JOB,
NETWORK_REMOTE_JOB,
"127.0.0.1", 12345,
&status);
mtapi_network_plugin_initialize("127.0.0.1", 12345, 5,
kElements * 4 * 3 + 32, &status);
float node_remote = 1.0f;
local_action = mtapi_action_create(
NETWORK_REMOTE_JOB,
AddVectorAction,
&node_remote, sizeof(float),
MTAPI_DEFAULT_ACTION_ATTRIBUTES,
&status);
float node_local = 1.0f;
action = mtapi_opencl_action_create(
OPENCL_JOB,
kernel, "AddVector", 32, 4,
&node_local, sizeof(float),
&status);
#include <embb/mtapi/c/mtapi_opencl.h>
const char * kernel =
"__kernel void test(\n"
" __global void* arguments,\n"
" int arguments_size,\n"
" __global void* result_buffer,\n"
" int result_buffer_size,\n"
" __global void* node_local_data,\n"
" int node_local_data_size) {\n"
" int ii = get_global_id(0);\n"
" int elements = arguments_size / sizeof(float) / 2;\n"
" if (ii >= elements)"
" return;"
" __global float* a = (__global float*)arguments;\n"
" __global float* b = ((__global float*)arguments) + elements;\n"
" __global float* c = (__global float*)result_buffer;\n"
" __global float* d = (__global float*)node_local_data;\n"
" c[ii] = a[ii] + b[ii] + d[0];\n"
"}\n";
...@@ -194,3 +194,126 @@ The root task can be started using \lstinline|embb::mtapi::Node::Spawn()| direct ...@@ -194,3 +194,126 @@ The root task can be started using \lstinline|embb::mtapi::Node::Spawn()| direct
Again, the started task has to be waited for (using \lstinline|embb::mtapi::Task::Wait()|) before the result can be returned. The runtime is shut down automatically in an \lstinline|atexit()| handler. Again, the started task has to be waited for (using \lstinline|embb::mtapi::Task::Wait()|) before the result can be returned. The runtime is shut down automatically in an \lstinline|atexit()| handler.
\emph{\textbf{Note:} If the node was initialized explicitly by calling \lstinline|embb::mtapi::Node::Initialize|, the runtime must also be shut down explicitly by calling \lstinline|embb::mtapi::Node::Finalize|.} \emph{\textbf{Note:} If the node was initialized explicitly by calling \lstinline|embb::mtapi::Node::Initialize|, the runtime must also be shut down explicitly by calling \lstinline|embb::mtapi::Node::Finalize|.}
\section{Plugins}
The \embb implementation of MTAPI provides an extension to allow for custom actions that are not executed by the scheduler for software actions as detailed in the previous sections.
Two plugins are delivered with \embb, one for supporting distributed systems through TCP/IP networking and the other to allow for transparently using OpenCL accelerators.
\subsection{Plugin API}
The plugin API consists of a single function named \lstinline|mtapi_ext_plugin_action_create()| contained in the mtapi\_ext.h header file. It is used to associate the plugin action with a specific job ID:
\begin{lstlisting}
mtapi_action_hndl_t mtapi_ext_plugin_action_create(
MTAPI_IN mtapi_job_id_t job_id,
MTAPI_IN mtapi_ext_plugin_task_start_function_t task_start_function,
MTAPI_IN mtapi_ext_plugin_task_cancel_function_t task_cancel_function,
MTAPI_IN mtapi_ext_plugin_action_finalize_function_t action_finalize_function,
MTAPI_IN void* plugin_data,
MTAPI_IN void* node_local_data,
MTAPI_IN mtapi_size_t node_local_data_size,
MTAPI_IN mtapi_action_attributes_t* attributes,
MTAPI_OUT mtapi_status_t* status
);
\end{lstlisting}
The plugin action is implemented through 3 callbacks, task start, task cancel and action finalize.
\lstinline|task_start_function| is called when the user requests execution of the plugin action by calling \lstinline|mtapi_task_start()| or \lstinline|mtapi_task_enqueue()|. To those functions the fact that they operate on a plugin action is transparent, they only require the job handle of the job the action was registered with.
\lstinline|task_cancel_function| is called when the user requests cancelation of a tasks by calling \lstinline|mtapi_task_cancel()| or by calling \lstinline|mtapi_queue_disable()| on a non-retaining queue.
\lstinline|action_finalize_function| is called when the node is finalized and the action is deleted, or when the user explicitly deletes the action by calling \lstinline|mtapi_action_delete()|.
For illustration our example plugin will provide a no-op action. The task start callback in that case looks like this:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_start_cb-snippet.h}
%
The scheduling operation is responsible for bringing the task to execution, this might involve instructing some hardware to execute the task or pushing the task into a queue for execution by a separate worker thread. Here however, the task is executed directly:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_schedule-snippet.h}
%
Since the task gets executed right away, it cannot be canceled and the task cancel callback implementation is empty:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_cancel_cb-snippet.h}
%
The plugin action did not acquire any resources so the action finalize callback is empty as well:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_action_finalize_cb-snippet.h}
%
Now that the callbacks are in place, the action can be registered with a job after the node was initialized using \lstinline|mtapi_initialize()|:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_action_create-snippet.h}
%
The job handle can now be obtained the normal MTAPI way. The fact that there is a plugin working behind the scenes is transparent by now:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_get_job-snippet.h}
%
Using the job handle tasks can be started like normal MTAPI tasks:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_start-snippet.h}
%
This call will lead to the invocation of then \lstinline|plugin_task_start| callback function, where the plugin implementor is responsible for bringing the task to execution.
\subsection{Network}
The MTAPI network plugin provides a means to distribute tasks over a TCP/IP network. As an example the following vector addition action is used:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_action_function-snippet.h}
%
It adds two float vectors and a float from node local data and writes the result into the result float vector. In the example code the vectors will hold \lstinline|kElements| floats each.
To use the network plugin, its header file needs to be included first:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_header-snippet.h}
%
After initializing the node using \lstinline|mtapi_initialize()|, the plugin itself needs to be initialized:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_plugin_initialize-snippet.h}
%
This will set up a listening socket on the localhost interface (127.0.0.1) at port 12345. The socket will allow a maximum of 5 connections and have a maximum transfer buffer size of \lstinline|kElements * 4 * 3 + 32|. This buffer size needs to be big enough to fit at least the argument and result buffer sizes at once. The example uses 3 vectors of \lstinline|kElements| floats using \lstinline|kElements * sizeof(float) * 3| bytes.
Since the example connects to itself on localhost, the "remote" action needs to be registered with the \lstinline|NETWORK_REMOTE_JOB|:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_remote_action_create-snippet.h}
%
After that, the local network action is created, that maps \lstinline|NETWORK_LOCAL_JOB| to \lstinline|NETWORK_REMOTE_JOB| through the network:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_local_action_create-snippet.h}
%
Now, \lstinline|NETWORK_LOCAL_JOB| can be used to execute tasks by simply calling \lstinline|mtapi_task_start()|. Their parameters will be transmitted through a socket connection and are consumed by the network plugin worker thread. The thread will start a task using the \lstinline|NETWORK_REMOTE_JOB|. When this task is finished, the results will be collected and sent back through the network. Again the network plugin thread will receive the results, provide them to the \lstinline|NETWORK_LOCAL_JOB| task and mark that task as finished.
When all work is done, the plugin needs to be finalized. This will stop the plugin worker thread and close the sockets:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_plugin_finalize-snippet.h}
%
Then the node may be finalized by calling \lstinline|mtapi_finalize()|.
\subsection{OpenCL}
The MTAPI OpenCL plugin allows the user to incorporate the computational power of an OpenCL accelerator, if one is available in the system.
The vector addition example from the network plugin is used again. However, the action function is an OpenCL kernel now:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_kernel-snippet.h}
%
The OpenCL plugin header file needs to be included first:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_header-snippet.h}
%
As with the network plugin, the OpenCL plugin needs to be initialized after the node has been initialized:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_plugin_initialize-snippet.h}
%
Then the plugin action can be registered with the \lstinline|OPENCL_JOB|:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_action_create-snippet.h}
%
The kernel source and the name of the kernel to use (AddVector) need to be specified while creating the action. The kernel will be compiled using the OpenCL runtime and the provided node local data transferred to accelerator memory. The local work size is the number of threads that will share OpenCL local memory, in this case 32. The element size instructs the OpenCL plugin how many bytes a single element in the result buffer consumes, in this case 4, as a single result is a single float. The OpenCL plugin will launch \lstinline|result_buffer_size/element_size| OpenCL threads to calculate the result.
Now the \lstinline|OPENCL_JOB| can be used like a normal MTAPI job to start tasks.
After all work is done, the plugin needs to be finalized. This will free all memory on the accelerator and delete the corresponding OpenCL context:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_plugin_finalize-snippet.h}
%
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment