00001 /* 00002 * IOchain - Distribute a chain of dependant IO events amoung threads. 00003 * 00004 * This file is part of Bitshuffle 00005 * Author: Kiyoshi Masui <kiyo@physics.ubc.ca> 00006 * Website: http://www.github.com/kiyo-masui/bitshuffle 00007 * Created: 2014 00008 * 00009 * See LICENSE file for details about copyright and rights to use. 00010 * 00011 * 00012 * Header File 00013 * 00014 * Similar in concept to a queue. Each task includes reading an input 00015 * and writing output, but the location of the input/output (the pointers) 00016 * depend on the previous item in the chain. 00017 * 00018 * This is designed for parallelizing blocked compression/decompression IO, 00019 * where the destination of a compressed block depends on the compressed size 00020 * of all previous blocks. 00021 * 00022 * Implemented with OpenMP locks. 00023 * 00024 * 00025 * Usage 00026 * ----- 00027 * - Call `ioc_init` in serial block. 00028 * - Each thread should create a local variable *size_t this_iter* and 00029 * pass its address to all function calls. Its value will be set 00030 * inside the functions and is used to identify the thread. 00031 * - Each thread must call each of the `ioc_get*` and `ioc_set*` methods 00032 * exactly once per iteration, starting with `ioc_get_in` and ending 00033 * with `ioc_set_next_out`. 00034 * - The order (`ioc_get_in`, `ioc_set_next_in`, *work*, `ioc_get_out`, 00035 * `ioc_set_next_out`, *work*) is most efficient. 00036 * - Have each thread call `ioc_end_pop`. 00037 * - `ioc_get_in` is blocked until the previous entry's 00038 * `ioc_set_next_in` is called. 00039 * - `ioc_get_out` is blocked until the previous entry's 00040 * `ioc_set_next_out` is called. 00041 * - There are no blocks on the very first iteration. 00042 * - Call `ioc_destroy` in serial block. 00043 * - Safe for num_threads >= IOC_SIZE (but less efficient). 00044 * 00045 */ 00046 00047 00048 #ifndef IOCHAIN_H 00049 #define IOCHAIN_H 00050 00051 00052 #include <stdlib.h> 00053 #ifdef _OPENMP 00054 #include <omp.h> 00055 #endif 00056 00057 00058 #define IOC_SIZE 33 00059 00060 00061 typedef struct ioc_ptr_and_lock { 00062 #ifdef _OPENMP 00063 omp_lock_t lock; 00064 #endif 00065 void *ptr; 00066 } ptr_and_lock; 00067 00068 typedef struct ioc_const_ptr_and_lock { 00069 #ifdef _OPENMP 00070 omp_lock_t lock; 00071 #endif 00072 const void *ptr; 00073 } const_ptr_and_lock; 00074 00075 00076 typedef struct ioc_chain { 00077 #ifdef _OPENMP 00078 omp_lock_t next_lock; 00079 #endif 00080 size_t next; 00081 const_ptr_and_lock in_pl[IOC_SIZE]; 00082 ptr_and_lock out_pl[IOC_SIZE]; 00083 } ioc_chain; 00084 00085 00086 void ioc_init(ioc_chain *C, const void *in_ptr_0, void *out_ptr_0); 00087 void ioc_destroy(ioc_chain *C); 00088 const void * ioc_get_in(ioc_chain *C, size_t *this_iter); 00089 void ioc_set_next_in(ioc_chain *C, size_t* this_iter, void* in_ptr); 00090 void * ioc_get_out(ioc_chain *C, size_t *this_iter); 00091 void ioc_set_next_out(ioc_chain *C, size_t *this_iter, void* out_ptr); 00092 00093 #endif // IOCHAIN_H 00094