/* * Copyright (C) <2009> Jefferson Science Associates, LLC * Under U.S. DOE Contract No. DE-AC05-06OR23177 * * Thomas Jefferson National Accelerator Facility * * Jefferson Lab * Scientific Computing Group, * 12000 Jefferson Ave., * Newport News, VA 23606 * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * ---------------------------------------------------------------------------- * Description: * GPU Message Passing Handler Header File * * GMH is a GPU Message Passing Handler for Multiple GPUs either on a * Host or on Multiple Hosts connected by Fast InterConnects. * * The inter-node transport mechanism is not specified. It can be MPI or * QMP. * * Author: * Jie Chen and Chip Watson * Scientific Computing Group * Jefferson Lab * * Revision History: * $Log: $ * */ #ifndef _GMH_H #define _GMH_H #include #include /** * Node and GPU Ranks * A rank is an integer consisting lower 4 bits for GPUs (maximum 16 GPUs/Node) * and higher 24 bits for CPUs (2^24 = 4 x 1024 x 1024 = 4 Millions) */ #define GMH_RANK(mpirank,gpuid) ((mpirank) << 4 + (gpuid) & (0xf)) /** * Retrieve MPI rank from GMH rank */ #define GMH_MPI_RANK(gmh_rank) ((gmh_rank) >> 4) /** * Retrieve GPU rank from GMH rank */ #define GMH_GPU_RANK(gmh_rank) ((gmh_rank) & (0xf)) /** * Error code for gmh package */ #define GMH_SUCCESS 0 #define GMH_DEVICE_NOT_FOUND -1 #define GMH_DEVICE_NOT_AVAILABLE -2 #define GMH_OUT_OF_HOST_MEMORY -3 #define GMH_INVALID_TASKLIST -10 #define GMH_INVALID_MEMORY_BUFFER -11 #define GMH_INVALID_MEM_HANDLE -12 #define GMH_RESOURCE_BUSY -13 #define GMH_OUTOF_RANGE -14 /** * Memory Flag Values */ #define GMH_MEM_READ_WRITE (1 << 1) #define GMH_MEM_READ_ONLY (1 << 2) #define GMH_MEM_WRITE_ONLY (1 << 3) /** * Event status values */ #define GMH_COMPLETE 0x0 #define GMH_RUNNING 0x1 #define GMH_SUBMITTED 0x2 #define GMH_QUEUED 0x3 /** * Control Task return status */ #define GMH_EXIT 0x0 #define GMH_RERUN 0x1 /** * Common used structures in gmh * * The real definition of these structures are hidden */ typedef struct _gmh_tasklist_t* gmh_tasklist_t; typedef struct _gmh_command_stream* gmh_stream_t; typedef struct _gmh_mem* gmh_mem_t; typedef struct _gmh_event* gmh_event_t; /** * Command stream property information name */ typedef char* qmh_stream_info_t; /** * Global reduction option types */ typedef int gmh_op_t; #define GMH_MAX (gmh_op_t)(0x12000001) #define GMH_MIN (gmh_op_t)(0x12000002) #define GMH_SUM (gmh_op_t)(0x12000003) #define GMH_PROD (gmh_op_t)(0x12000004) #define GMH_LAND (gmh_op_t)(0x12000005) #define GMH_BAND (gmh_op_t)(0x12000006) #define GMH_LOR (gmh_op_t)(0x12000007) #define GMH_BOR (gmh_op_t)(0x12000008) #define GMH_LXOR (gmh_op_t)(0x12000009) #define GMH_BXOR (gmh_op_t)(0x1200000a) /** * Global reduction operation types */ typedef int gmh_datatype_t; #define GMH_CHAR ((gmh_datatype_t)0x4c000101) #define GMH_SIGNED_CHAR ((gmh_datatype_t)0x4c000118) #define GMH_UNSIGNED_CHAR ((gmh_datatype_t)0x4c000102) #define GMH_BYTE ((gmh_datatype_t)0x4c00010d) #define GMH_WCHAR ((gmh_datatype_t)0x4c00040e) #define GMH_SHORT ((gmh_datatype_t)0x4c000203) #define GMH_UNSIGNED_SHORT ((gmh_datatype_t)0x4c000204) #define GMH_INT ((gmh_datatype_t)0x4c000405) #define GMH_UNSIGNED ((gmh_datatype_t)0x4c000406) #define GMH_LONG ((gmh_datatype_t)0x4c000807) #define GMH_UNSIGNED_LONG ((gmh_datatype_t)0x4c000808) #define GMH_FLOAT ((gmh_datatype_t)0x4c00040a) #define GMH_DOUBLE ((gmh_datatype_t)0x4c00080b) #define GMH_LONG_DOUBLE ((gmh_datatype_t)0x4c00100c) #define GMH_LONG_LONG_INT ((gmh_datatype_t)0x4c000809) #define GMH_UNSIGNED_LONG_LONG ((gmh_datatype_t)0x4c000819) #define GMH_LONG_LONG GMH_LONG_LONG_INT #ifdef __cplusplus extern "C" { #endif /** * Thread launch function provided by applications */ typedef void* (gmh_thread_func_t) (gmh_tasklist_t list, void *arg); /** * GPU Kernel Launch Function provided by applications */ typedef int (gmh_gpu_kernel_t) (gmh_stream_t stream, void* arg); /** * CPU control task: return GMH_EXIT to empty task list (no more loop) */ typedef int (gmh_control_task_t) (gmh_task_list_t list, void* arg); /** * Initialize gmh code package. * This routine should be called after a thread is launched * and a GPU device is attached. * * This code then is called inside a spawned thread, not in main thread * * @param list created new gmh task list for this thread * @param gpuid GPU device id for this thread * * @return GMH_SUCESS if everything is ok. */ extern int gmh_th_init (gmh_tasklist_t* list, int gpuid); /** * Finialize gmh threaded package * This routime should be called when a thread is ready to quit gmh * * @param list task list associated with this thread. * * @return GMH_SUCCESS if all resources are freed. */ extern int gmh_th_fini (gmh_tasklist_t list); /** * Initialize gmh package from main thread * * This call will automatically spawn necessary threads to match requested * number of GPUs. * * @param lists newly allocated task lists populated in preallocated array * of pointers. * @param numgpus request number of GPUs * @param func a user provide thread entry function that handles a GPU device * @param arg a user provide arbitrary data pointer used by thread entry func * * @return GMH_SUCCESS if everything is ok, Return GMH_DEVICE_NOT_AVAILABLE or * GMH_OUT_OF_HOST_MEMORY on failure. */ extern int gmh_init (gmh_tasklist_t* lists[], int numgpus, gmh_thread_func_t func, void* arg); /** * Clean a task list * This call clears out all tasks on the list consisting multiple streams * * @param list a task list to clear * * @return returns GMH_SUCCESS if every task is removed. It returns * GMH_RESOURCE_BUSY if there are tasks on the list still in execution mode. */ extern int gmh_tasklist_clear (gmh_tasklist_t list); /** * Get some information related to a context * * @param list a gmh task list for a thread * @param gpuid returned gpu is this context (thread) is using * @return returns GMH_SUCCESS on success. Returns GMH_INVALID_TASKLIST if the * list is invalid. */ extern int gmh_tasklist_get_gpuid (gmh_tasklist_t list, int* gpuid); /** * Create a memory object for a GPU memory buffer * An application has to allocate GPU memory before calling this routine * * @param list a gmh task list (thread) * @param flag memory buffer flag: GMH_MEM_READ_WRITE, GMH_MEM_READ_ONLY, * GMH_MEM_WRITE_ONLY * @param gpu_buffer a memory buffer allocated on gpu by this thread * @param buffer_size the buffer size for the gpu memory buffer * @param mem return gmh memory handle * * @return returns GMH_SUCCESS on success. Otherwise returns * GMH_INVALID_TASKLIST or GMH_INVALID_MEMORY_BUFFER */ extern int gmh_create_mem (gmh_tasklist_t list, int flag, void* gpu_buffer, unsigned int buffer_size, gmh_mem_t* mem); /** * Free gmh memory object, but not user allocated memory buffer * @param mem memory object handler * @return returns GMH_SUCCESS on success. Otherwise returns * GMH_INVALID_MEM_HANDLE */ extern int gmh_destroy_mem (gmh_mem_t mem); /** * Create a command stream for GPU kernels and GPU memory buffer communication * This stream for now is strict FIFO. Future out of order execution may be * possible * * @param list gmh task list (thread) controlling a GPU * @param stream a newly created command stream * @param flags currently is unused * * @return this routine returns GMH_SUCCESS when a new stream is created, * otherwise it returns GMH_INVALID_TASKLIST, GMH_OUT_OF_HOST_MEMORY */ extern int gmh_create_command_stream (gmh_tasklist_t list, gmh_stream_t* stream, int flags); /** * Free a command stream * @param stream a command stream to free * * @return the routine returns GMH_SUCCESS */ extern int gmh_destroy_command_stream (gmh_stream_t stream); /** * Get command stream information such as CUDA stream associated with * this queue * * @param stream the command queue we are interested in * @param name the property name we are going after * @param info_size a pointer to user allocated memory buffer size holding * returned value * @param info_value a memory allocated by user to hold returned value * * @return returns GMH_SUCCESS if everything is ok. returns GMH_OUTOF_RANGE when * user allocated memory is smaller than the returned value required. */ extern int gmh_get_command_stream_info (qmh_stream_t stream, qmg_stream_info_t name, unsigned int* info_size, void* info_value); /** * Add a receiving memory action to the command stream * * @param stream the receiving memory action is posted on this queue * @param mem a receiving memory buffer * @param block_recv a boolean variable indicating whether this is a blocked * call * @param recv_from a remote gpu id to receive data from * @param tag a mpi style tag to distinguish messages * @param num_events_to_wait the number of events to wait before this receive * @param events_to_wait the array of events to wait before this receive * @param event newly generated event for this action * * @return this call returns GMH_SUCCESS on successful posting. */ extern int gmh_add_receive_buffer (gmh_stream_t stream, gmh_mem_t mem, int block_recv, int recv_from, int tag, unsigned int num_events_to_wait, gmh_event_t* events_to_wait, gmh_event_t* event); /** * Enqueue a sending memory action to the command stream * * @param stream the sending memory action is posted on this stream * @param mem a sending memory buffer * @param block_send a boolean variable indicating whether this is a blocked * call * @param send_to a remote gpu id to send data to * @param tag a mpi style tag to distinguish messages * @param num_events_to_wait the number of events to wait before this receive * @param events_to_wait the array of events to wait before this receive * @param event newly generated event for this action * * @return this call returns GMH_SUCCESS on successful posting. */ extern int gmh_add_send_buffer (gmh_stream_t stream, gmh_mem_t mem, int block_send, int send_to, int tag, unsigned int num_events_to_wait, gmh_event_t* events_to_wait, gmh_event_t* event); /** * Enqueue a GPU kernel to the command stream * * @param stream the command stream this action is post to * @param func a user supplied kernel launch function which laucnes GPU kernel * using user controlled grid, block and shared memory. The function should * call gmh_get_stream_info to retrieve critical information. * @param arg user supplied argument used in kernel * @param num_events_to_wait the number of events to wait before this receive * @param events_to_wait the array of events to wait before this receive * @param event newly generated event for this action * * @return this call returns GMH_SUCCESS on successful posting. */ extern int gmh_add_gpu_kernel (gmh_stream_t stream, gmh_gpu_kernel_t func, void* arg, unsigned int num_events_to_wait, gmh_event_t* events_to_wait, gmh_event_t* event); /** * Add a CPU task supplied by user. The task signals the task list to * exit * This call should be the last call after all tasks. * * @param list the task list (a single thread) * @param task a user supplied cpu task to signal exit or not. If the task * returns GMH_EXIT, the task list will be cleared. */ exterm int gmh_add_control_task (gmh_tasklist_t list, gmh_control_task_t task, void *arg); /** * Add a GPU control kernel supplied by user. The task signals the task list to * exit * This call should be the last call after all tasks. * * @param list the task list (a single thread) * @param control_flag a memory location for CPU to read control status * @param func a user supplied gpu task to signal exit or not. This kernel * func writes integer status (GMH_EXIT | GMH_RERUN) at control_flag location. * */ exterm int gmh_add_control_kernel (gmh_tasklist_t list, gmh_mem_t control_flag, gmh_gpu_kernel_t func, void* arg); /** * Start executing all commands in the task list */ extern int gmh_start (gmh_tasklist_t list); /** * Create a global reduction action across multiple queues and multiple cxts * Every thread has to issue this command * * @param list the task list of this thread * @param send_buf initial output buffer to do reduction on * @param recv_buf final buffer holds the reduction values * @param op what kind of global reduction to carry out * * @return return GMH_SUCCESS when success */ extern int gmh_reduce (gmh_tasklist_t list, gmh_mem_t send_buf, gmh_mem_t recv_buf, gmh_datatype_t type, gmh_op_t op); /** * Create a global barrier among all GPUs * * @param list a task list containing this barrier. This implies all tasks * before this barrier will be finished after this call. * * @reurn returns GMH_SUCCESS */ extern int gmh_barrier (gmh_tasklist_t list); /** * Wait for multiple events for finish * * @param num_events The number of events to wait for * @param events the array of events to wait for * * @return returns QMH_SUCCESS (GMH_COMPLETE) when all events finished. */ extern int gmh_wait_for_events (unsigned int num_events, gmh_event_t* events); /** * Get event information * * Return event information GMH_COMPLETE and so on */ extern int gmh_get_event_info (gmh_event_t* event); /** * Release event after this event is finished * This call will not do anything if the event is not finished * * @param event a event handle to free * * @return returns GMH_SUCCESS otherwise returns GMH_RESOURCE_BUSY */ extern int gmh_release_event (gmh_event_t event); #ifdef __cplusplus } #endif #endif