DiCE API nvidia_logo_transpbg.gif Up
mi::neuraylib::IFragmented_job Class Referenceabstract

This interface represents the base class for all fragmented jobs. More...

#include <dice.h>

Inheritance diagram for mi::neuraylib::IFragmented_job:

Public Types

enum  Scheduling_mode {
  LOCAL = 0 ,
  CLUSTER = 1 ,
  ONCE_PER_HOST = 2 ,
  USER_DEFINED = 3 ,
  SCHEDULING_MODE_FORCE_32_BIT = 0xffffffffU
}
 Constants for possible scheduling modes. More...
 
- Public Types inherited from mi::base::Interface_declare< 0x037f3783, ... >
typedef Interface_declare< id1, ... > Self
 Own type. More...
 
typedef Uuid_t< id1, ... > IID
 Declares the interface ID (IID) of this interface. More...
 
- Public Types inherited from mi::base::Interface_declare< 0x7a70f2fb, ... >
typedef Interface_declare< id1, ... > Self
 Own type. More...
 
typedef Uuid_t< id1, ... > IID
 Declares the interface ID (IID) of this interface. More...
 
- Public Types inherited from mi::base::IInterface
typedef Uuid_t<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0> IID
 Declares the interface ID (IID) of this interface. More...
 

Public Member Functions

virtual void execute_fragment (IDice_transaction *transaction, Size index, Size count, const IJob_execution_context *context)=0
 Executes one of many fragments of the fragmented job on the local host. More...
 
virtual void execute_fragment_remote (ISerializer *serializer, IDice_transaction *transaction, Size index, Size count, const IJob_execution_context *context)=0
 Executes one of many fragments of the fragmented job on a remote host. More...
 
virtual void receive_remote_result (IDeserializer *deserializer, IDice_transaction *transaction, Size index, Size count)=0
 Receives the result generated by the remote execution of a fragment. More...
 
virtual IRDMA_bufferget_rdma_result_buffer (IRDMA_context *rdma_context, Size index)=0
 Returns an RDMA buffer to be used for the result of the fragment. More...
 
virtual IRDMA_bufferexecute_fragment_remote_rdma (IDice_transaction *transaction, Size index, Size count, IRDMA_context *rdma_context, const IJob_execution_context *context)=0
 Executes one of many fragments of the fragmented job on a remote host (RDMA variant). More...
 
virtual void receive_remote_result_rdma (IRDMA_buffer *buffer, IDice_transaction *transaction, Size index, Size count)=0
 Receives the result generated by the remote execution of a fragment (RDMA variant). More...
 
virtual void serialize (ISerializer *serializer) const =0
 Serializes the fragmented job to enable remote job execution of fragments. More...
 
virtual void deserialize (IDeserializer *deserializer)=0
 Deserializes the fragmented job to enable remote job execution of fragments. More...
 
virtual void assign_fragments_to_hosts (Uint32 *slots, Size nr_slots)=0
 Static assignment of fragments to hosts in the cluster. More...
 
virtual Scheduling_mode get_scheduling_mode () const =0
 Returns the scheduling mode. More...
 
virtual Float32 get_cpu_load () const =0
 Returns the CPU load per fragment of the fragmented job. More...
 
virtual Float32 get_gpu_load () const =0
 Returns the GPU load per fragment of the fragmented job. More...
 
virtual void cancel ()=0
 Cancels the execution of not yet completed jobs. More...
 
virtual Sint8 get_priority () const =0
 Returns the priority of the job. More...
 
virtual Size get_thread_limit () const =0
 Returns the maximum number of threads that should be used to execute the fragments of this job. More...
 
virtual bool get_allow_non_sequential_chunks () const =0
 Indicates whether chunks can be delivered out of order. More...
 
- Public Member Functions inherited from mi::neuraylib::ISerializable
virtual base::Uuid get_class_id () const =0
 Returns the class ID of the object. More...
 
virtual void serialize (ISerializer *serializer) const =0
 Serializes the object to the given serializer. More...
 
virtual void deserialize (IDeserializer *deserializer)=0
 Deserializes the object from the given deserializer. More...
 
- Public Member Functions inherited from mi::base::IInterface
virtual Uint32 retain () const =0
 Increments the reference count. More...
 
virtual Uint32 release () const =0
 Decrements the reference count. More...
 
virtual const IInterfaceget_interface (const Uuid &interface_id) const =0
 Acquires a const interface from another. More...
 
template<class T>
const T * get_interface () const
 Acquires a const interface from another. More...
 
virtual IInterfaceget_interface (const Uuid &interface_id)=0
 Acquires a mutable interface from another. More...
 
template<class T>
T * get_interface ()
 Acquires a mutable interface from another. More...
 
virtual Uuid get_iid () const =0
 Returns the interface ID of the most derived interface. More...
 

Additional Inherited Members

- Static Public Member Functions inherited from mi::base::Interface_declare< 0x037f3783, ... >
static bool compare_iid (const Uuid &iid)
 Compares the interface ID iid against the interface ID of this interface and of its ancestors. More...
 
- Static Public Member Functions inherited from mi::base::Interface_declare< 0x7a70f2fb, ... >
static bool compare_iid (const Uuid &iid)
 Compares the interface ID iid against the interface ID of this interface and of its ancestors. More...
 
- Static Public Member Functions inherited from mi::base::IInterface
static bool compare_iid (const Uuid &iid)
 Compares the interface ID iid against the interface ID of this interface. More...
 

Detailed Description

This interface represents the base class for all fragmented jobs.

Each fragmented job must be derived from the this interface.

Fragmented jobs enable distributing compute intensive work to the CPUs and/or GPUs available in a cluster environment.

Compared to a database jobs, fragmented jobs are lightweight means to achieve distributed, parallel computing in a cluster. Fragmented jobs differ from database jobs as follows:

  • A fragmented job is not stored in the database but instantiated on demand to be executed immediately.
  • Each instance of a fragmented job splits into a pre-defined number of fragments each of which executes independently possibly on different CPUs and/or GPUs in the cluster.
  • A fragmented job does not return a result but the execution function may operate on the members of the fragmented job class instance to store results. Note that it is necessary to synchronize accesses to those members from different fragments because they may be executed in parallel.

In general, a fragmented job should be used if the result of the parallel algorithm is used only once by the host initiating the execution. For instance, a fragmented job for rendering may initiate the rendering of a single frame.

Note
Database jobs represent a different way to achieve parallelism in a cluster environment. See mi::neuraylib::IJob for details.
See also
The mixin mi::neuraylib::Fragmented_job can be useful as a starting point for your own implementation of this abstract interface.

Member Enumeration Documentation

 Scheduling_mode

Constants for possible scheduling modes.

See also
mi::neuraylib::IFragmented_job::get_scheduling_mode()
Enumerator
LOCAL 

All fragments will be done on the local host.

In consequence, dummy implementations for serialize() and deserialize() as well as for execute_fragment_remote() and receive_remote_result() suffice.

CLUSTER 

The fragments will be spread across all hosts in the cluster.

If a fragment fails to execute on a given host (for example, due to a host leaving the cluster), it is re-assinged to a different host such that fragments are guaranteed to be executed.

Note
Although DiCE tries to distribute fragments in a fair manner to the cluster nodes, there is no guarantee that this will be the case.
ONCE_PER_HOST 

At most one fragment will be done per remote host.

If the specified number of fragments is larger than zero and less than the number of remote hosts then only some hosts will get a fragment. To ensure that exactly one fragment will be done per remote host the number of fragments should be set to the special value 0. This mode is not possible for jobs which need a GPU.

Note
Only hosts which are in the same sub cluster are eligible for executing a fragment of the job.
USER_DEFINED 

The job implements an explicit assignment of fragments to hosts and must implement the assign_fragments_to_hosts() function to fill out all slots.

Fragments assigned to hosts which are unknown will be skipped. If a host fails during fragment execution, its workload will not be re-assinged to a different host

Member Function Documentation

 assign_fragments_to_hosts()

virtual void mi::neuraylib::IFragmented_job::assign_fragments_to_hosts ( Uint32 slots,
Size  nr_slots 
)
pure virtual

Static assignment of fragments to hosts in the cluster.

The static assignment of fragments to hosts in the cluster overrides the DiCE built-in scheduling of fragments to hosts by providing an array of host IDs that are mapped to the fragments' indices, i.e., by assigning fragments to hosts explicitly.

Example: The array 1, 2, 2, 2, 3 would map the first fragment with index 0 to host ID 1, the next three fragments to host ID 2, and the last fragment with index 4 to host ID 3.

A typical use case for static assignments represent sort-last algorithms. Sort-last algorithms subdivide the (huge) data to be processed into smaller portions and then delegate the smaller portions to hosts once. This avoids network transfers while the processing the data later. The static assignment then ensure that the fragment for processing a certain portion of the data are scheduled for the host in the cluster where the portion resides.

Care should be taken when implementing a static user-defined assignment. Usually, the DiCE built-in scheduler balances the workload of compute intensive tasks itself. The static user-defined assignment of jobs to hosts circumvents this feature which might results in an unbalanced non-scalable system when done improperly.

Note
In case the assigned host ID is not a valid one, DiCE will silently skip the execution of the fragment. An application which needs to have all fragments executed should note which fragments have been done, when the job finished, and re-schedule any missing fragments.
Parameters
slotsPointer to an array of host IDs. The i-th element is the host ID of the i-th fragment.
nr_slotsThe size of the array slots.

 cancel()

virtual void mi::neuraylib::IFragmented_job::cancel ( )
pure virtual

Cancels the execution of not yet completed jobs.

This method is called if the job has been submitted for execution, but not all its fragments have been completed when the transaction is closed or aborted. If the job result is no longer needed in such a case, this notification can be used to terminate currently running fragments and/or skip the execution of not yet started fragments.

 deserialize()

virtual void mi::neuraylib::IFragmented_job::deserialize ( IDeserializer deserializer)
pure virtual

Deserializes the fragmented job to enable remote job execution of fragments.

The method creates a replica of the serialized original fragmented job instance on the remote host. The deserialized replica is used for all fragments of a fragmented job that are executed on that particular host, i.e., they all share the same data. In consequence, the class may additionally generate data required by all fragments, like caches, etc.

Parameters
deserializerThe deserializer from which to read the job content.

Implements mi::neuraylib::ISerializable.

 execute_fragment()

virtual void mi::neuraylib::IFragmented_job::execute_fragment ( IDice_transaction transaction,
Size  index,
Size  count,
const IJob_execution_context context 
)
pure virtual

Executes one of many fragments of the fragmented job on the local host.

Executes one fragment of the many fragments spawned by the fragmented job. This method is used for fragments executed on the calling host only and, thus, operates on the original instance of the fragmented job class and not on a copy.

Note that other fragments operating on the same instance might be executed in parallel. Therefore all accesses to instance data need to be properly serialized.

See also
execute_fragment_remote() and receive_remote_result() are the counterpart of this method for remote execution
execute_fragment_remote_rdma() and receive_remote_result_rdma() are the counterparts of this method for remote execution using RDMA
Parameters
transactionThe transaction in which the fragmented job is executed. The transaction can be used to access database elements and database jobs required for execution but should not be used to edit or create tags. Might be NULL if the fragmented job was started without transaction.
indexThe index of the fragment to be executed. The value is in the range from 0 to count-1.
countThe number of fragments into which the fragmented job is split.
contextThe context in which the fragmented job is executed.

 execute_fragment_remote()

virtual void mi::neuraylib::IFragmented_job::execute_fragment_remote ( ISerializer serializer,
IDice_transaction transaction,
Size  index,
Size  count,
const IJob_execution_context context 
)
pure virtual

Executes one of many fragments of the fragmented job on a remote host.

Executes one fragment of the many fragments spawned by the fragmented job on a remote host. The remote execution requires the remote host to generate a replica of the original fragmented job instance using serialize() on the local host and deserialize() on the remote host.

Note that all fragments of a fragmented job which are executed on the same host will use the same replica of the original fragmented job instance. That means the replica can contain data shared between different fragments, like caches, etc.

As in the case of local execution other fragments executed on that host might be executed in parallel. Therefore all accesses to instance data need to be properly synchronized.

Intermediate results can be returned by calling mi::neuraylib::ISerializer::flush() on serializer. All data serialized until that point will be delivered in a single call to receive_remote_result(). When execute_fragment_remote() returns any data not yet flushed will be flushed and receive_remote_result() will be called one last time with that data.

Parameters
serializerThe serializer used to send the result of that fragment back to the initiating host (see receive_remote_result()).
transactionThe transaction in which the fragmented job is executed. The transaction can be used to access database elements and database jobs required for execution but should not be used to edit or create tags.
indexThe index of the fragment to be executed. The value is in the range from 0 to count-1.
countThe number of fragments into which the fragmented job is split.
contextThe context in which the fragmented job is executed.
See also
receive_remote_result() consumes the data produced by this method
execute_fragment() is the counterpart of this method for local execution
execute_fragment_remote_rdma() and receive_remote_result_rdma() are the counterparts of this method for remote execution using RDMA

 execute_fragment_remote_rdma()

virtual IRDMA_buffer * mi::neuraylib::IFragmented_job::execute_fragment_remote_rdma ( IDice_transaction transaction,
Size  index,
Size  count,
IRDMA_context rdma_context,
const IJob_execution_context context 
)
pure virtual

Executes one of many fragments of the fragmented job on a remote host (RDMA variant).

Executes one fragment of the many fragments spawned by the fragmented job on a remote host. The remote execution requires the remote host to generate a replica of the original fragmented job instance using serialize() on the local host and deserialize() on the remote host.

Note that all fragments of a fragmented job which are executed on the same host will use the same replica of the the original fragmented job instance. That means the replica can contain data shared between different fragments, like caches, etc.

As in the case of local execution other fragments executed on that host might be executed in parallel. Therefore all accesses to instance data need to be properly synchronized.

Parameters
transactionThe transaction in which the fragmented job is executed. The transaction can be used to access database elements and database jobs required for execution but should not be used to edit or create tags.
indexThe index of the fragment to be executed. The value is in the range from 0 to count-1.
countThe number of fragments into which the fragmented job is split.
rdma_contextThe RDMA context to acquire RDMA buffers from for this host.
contextThe context in which the fragmented job is executed.
Returns
The RDMA buffer with the result of this fragment (allocated from rdma_context) or NULL if no result is to be send back from this fragment. The same RDMA buffer can be returned from multiple fragments and from different jobs, in that case it will be sent back as the result of all the fragments using it.
Note that the returned RDMA buffer has to stay unchanged as long as the reception has not been confirmed from the receiving side. At this time the system will return the buffer to the RDMA context, so that it can be used for further transmissions.
Note that allocation of the RDMA buffer from rdma_context will fail if its size exceeds the size of the RDMA buffer allocated for this fragment on the receiver side.
See also
receive_remote_result_rdma() produces the data consumed by this method
execute_fragment() is the counterpart of this method and receive_remote_result_rdma() for local execution
execute_fragment_remote() and receive_remote_result() are the counterparts of this method and receive_remote_result_rdma() for remote execution without RDMA

 get_allow_non_sequential_chunks()

virtual bool mi::neuraylib::IFragmented_job::get_allow_non_sequential_chunks ( ) const
pure virtual

Indicates whether chunks can be delivered out of order.

 get_cpu_load()

virtual Float32 mi::neuraylib::IFragmented_job::get_cpu_load ( ) const
pure virtual

Returns the CPU load per fragment of the fragmented job.

Typically 1.0 for CPU jobs and 0.0 for GPU jobs. A value larger than 1.0 might be used for jobs that concurrently use multiple threads per fragment, e.g., if OpenMP or MPI is used. A value between 0.0 and 1.0 might be used for jobs that do not much work themselves, but are rather used as synchronization primitive.

Note
This value must never change for a given instance of the fragmented job.

 get_gpu_load()

virtual Float32 mi::neuraylib::IFragmented_job::get_gpu_load ( ) const
pure virtual

Returns the GPU load per fragment of the fragmented job.

Typically 0.0 for CPU jobs and 1.0 for GPU jobs. A value larger than 1.0 might be used for jobs that concurrently use multiple GPUs per fragment. A value between 0.0 and 1.0 might be used for jobs that do not much work themselves, but are rather used as synchronization primitive.

Note
This value must never change for a given instance of the fragmented job.

 get_priority()

virtual Sint8 mi::neuraylib::IFragmented_job::get_priority ( ) const
pure virtual

Returns the priority of the job.

The smaller the value the higher the priority of the job to be executed.

Note
Negative values are reserved for internal purposes.

 get_rdma_result_buffer()

virtual IRDMA_buffer * mi::neuraylib::IFragmented_job::get_rdma_result_buffer ( IRDMA_context rdma_context,
Size  index 
)
pure virtual

Returns an RDMA buffer to be used for the result of the fragment.

Used to allocate an RDMA buffer which will be used to store the result of a fragment execution on a remote host. This method is only called for fragments which are executed on remote hosts. The RDMA buffer must be obtained from the given RDMA context.

If the method returns a valid RDMA buffer, the methods execute_fragment_remote_rdma() and receive_remote_result_rdma() are used instead of execute_fragment_remote() and receive_remote_result() to execute a fragment and to receive its result.

The RDMA buffer must at least be able to store the maximum expected result of the fragment execution.

Note
If RDMA is not available on the system, the behavior will be the same as if RDMA would be used, only the performance might be lower.
Parameters
rdma_contextRDMA context to acquire buffers from for this host.
indexThe index of the fragment to be executed.
Returns
The RDMA buffer or NULL if RDMA should not be used.

 get_scheduling_mode()

virtual Scheduling_mode mi::neuraylib::IFragmented_job::get_scheduling_mode ( ) const
pure virtual

Returns the scheduling mode.

Returns
The scheduling mode for the fragmented job.

 get_thread_limit()

virtual Size mi::neuraylib::IFragmented_job::get_thread_limit ( ) const
pure virtual

Returns the maximum number of threads that should be used to execute the fragments of this job.

With certain job patterns a large number of threads might be used to execute as many fragments as possible in parallel. This property can be used to limit the number of threads, potentially at the cost of performance. The special value 0 means no limit on the number of threads.

 receive_remote_result()

virtual void mi::neuraylib::IFragmented_job::receive_remote_result ( IDeserializer deserializer,
IDice_transaction transaction,
Size  index,
Size  count 
)
pure virtual

Receives the result generated by the remote execution of a fragment.

This method is called by the host that initiated the fragmented job execution for each fragment that has been executed on a remote host. The method receives via deserializer the data that has been written to the serializer on the remote host by execute_fragment_remote().

This method is called on the original instance of the fragmented job. Note that other fragments operating on the same instance might receive their result in parallel. Therefore all accesses to instance data need to be properly serialized.

Essentially, the remote execution of fragments of a fragmented job using execute_fragment_remote() on the remote host and receive_remote_result() on the local host should have the same effect as executing execute_fragment() on the local host.

The remote execution of a fragment might produce intermediate results by flushing the data serialized so far. Each call to mi::neuraylib::ISerializer::flush() on the remote host will result in a single call to receive_remote_result() on the local host, even if no data was flushed. When the execution on the remote host finishes this method will be called one last time with the remaining data.

Parameters
deserializerThe deserializer used to receive the result of that fragment from the remote host.
transactionThe transaction in which the fragmented job is executed. The transaction can be used to access database elements and database jobs required for execution but should not be used to edit or create tags.
indexThe index of the fragment to be executed. The value is in the range from 0 to count-1.
countThe number of fragments into which the fragmented job is split.
See also
execute_fragment_remote() produces the data consumed by this method
execute_fragment() is the counterpart of this method for local execution
execute_fragment_remote_rdma() and receive_remote_result_rdma() are the counterparts of this method for remote execution using RDMA

 receive_remote_result_rdma()

virtual void mi::neuraylib::IFragmented_job::receive_remote_result_rdma ( IRDMA_buffer buffer,
IDice_transaction transaction,
Size  index,
Size  count 
)
pure virtual

Receives the result generated by the remote execution of a fragment (RDMA variant).

This method is called by the host that initiated the fragmented job execution for each fragment that has been executed on a remote host. The method receives via buffer the data that has been returned in the RDMA buffer on the remote host by execute_fragment_remote_rdma().

This method is called on the original instance of the fragmented job. Note that other fragments operating on the same instance might receive their result in parallel. Therefore all accesses to instance data need to be properly serialized.

Essentially, the remote execution of fragments of a fragmented job using execute_fragment_remote_rdma() on the remote host and receive_remote_result_rdma() on the local host should have the same effect as executing execute_fragment() on the local host.

Parameters
bufferThe RDMA buffer obtained from get_rdma_result_buffer(). It contains the data returned by execute_fragment_remote_rdma() on the remote host. The data might be processed immediately, but it is also possible to retain the buffer and to process it later.
transactionThe transaction in which the fragmented job is executed. The transaction can be used to access database elements and database jobs required for execution but should not be used to edit or create tags.
indexThe index of the fragment to be executed. The value is in the range from 0 to count-1.
countThe number of fragments into which the fragmented job is split.
See also
execute_fragment_remote_rdma() produces the data consumed by this method
execute_fragment() is the counterpart of this method and execute_fragment_remote_rdma() for local execution
execute_fragment_remote() and receive_remote_result() are the counterparts of this method and execute_fragment_remote_rdma() for remote execution without RDMA

 serialize()

virtual void mi::neuraylib::IFragmented_job::serialize ( ISerializer serializer) const
pure virtual

Serializes the fragmented job to enable remote job execution of fragments.

The serialization shall include all members required for remote fragment execution. If the fragmented job references objects by means of tags it suffices to serializes the tags only. The remote execution can then access these tags and the distributed database ensures that the objects get transferred to the requesting remote host.

Parameters
serializerThe serializer to which to write the job content to.

Implements mi::neuraylib::ISerializable.