
                    Equalizer n-body example for CUDA

Overview
  
  The purpose of this simple example is to demonstrate how Equalizer can be used
  to perform distributed GPU computing tasks using CUDA. We illustrate the basic
  principles of how compute data can be shared across different nodes in a 
  typical configuration using common Equalizer functionality. As a consequence, 
  the memory update mechanism is not optimal for multi-GPU configurations .

  The simulation code is based on the article "Fast N-body Simulation with CUDA" 
  by Lars Nyland, Mark Harris, and Jan F. Prins. 
  
Current design implications
  
  We use the compound mechanism to control the task scheduling (through a 2D 
  range) the GPU computing related functionality thus has to be implemented in 
  the draw function of the channel.
  
Data distribution

  Initially, the whole dataset is distributed to all nodes of the config using 
  the common framedata mechanism. Each participating pipe is then responsible 
  for updating and rendering a specific subset of the shared data (see [1]). 
  
  The data synchronization is handled by a SharedData facade object owned by 
  the pipe objects, which in turn uses a FrameData and SharedDataProxy objects 
  to map remote shared memory (see [2]). This approach requires a 2-stage 
  initialisation phase, as each channel must receive the IDs of all the proxy 
  objects through the framedata mechanism before using them. 
  
  The communication from the nodes to the application is implemented using 
  custom config events.
  
Configuration files

  We use the hint_cuda_GL_interop in conjunction with the pipe device number to 
  enable correct CUDA initialization. A few examples are available in the config
  subfolder.
  
  [1] Please note that in this example every node updates its data subset each 
      frame, which then has to be transferred to all other nodes (and GPUs!) to 
      compute the next frame. This is a worst-case scenario and should be 
      avoided in real production code! 
	  
  [2] For simplicity reasons, the local data proxy always has index 0.
