1 // Copyright 2019, University of Freiburg. 2 // Chair of Algorithms and Data Structures. 3 // Markus Näther <naetherm@informatik.uni-freiburg.de> 4 5 module derelict.curand.curand; 6 7 import derelict.util.loader; 8 import derelict.cuda.runtimeapi; 9 10 private 11 { 12 import derelict.util.system; 13 14 static if(Derelict_OS_Windows) 15 enum libNames = "curand32_100.dll,curand64_100.dll"; 16 else static if (Derelict_OS_Mac) 17 enum libNames = "libcurand.dylib,/usr/local/lib/libcurand.dylib"; 18 else static if (Derelict_OS_Linux) 19 { 20 version(X86) 21 enum libNames = "libcurand.so,libcurand.so.10.0,/opt/cuda/lib/libcurand.so"; 22 else version(X86_64) 23 enum libNames = "libcurand.so,libcurand.so.10.0,/opt/cuda/lib64/libcurand.so,/usr/lib/x86_64-linux-gnu/libcurand.so.10.0"; 24 else 25 static assert(0, "Need to implement CUDA libNames for this arch."); 26 } 27 else 28 static assert(0, "Need to implement CUDA libNames for this operating system."); 29 } 30 31 32 // curand_discrete.h: 33 34 35 /** 36 * CURAND distribution 37 */ 38 /** \cond UNHIDE_TYPEDEFS */ 39 alias curandDistribution_st = double; 40 alias curandDistribution_t = curandDistribution_st*; 41 /** \endcond */ 42 /** 43 * CURAND distribution M2 44 */ 45 /** \cond UNHIDE_TYPEDEFS */ 46 alias curandHistogramM2K_st = uint; 47 alias curandHistogramM2K_t = curandHistogramM2K_st*; 48 alias curandHistogramM2V_st = curandDistribution_st; 49 alias curandHistogramM2V_t = curandHistogramM2V_st *; 50 51 alias curandDiscreteDistribution_t = curandDiscreteDistribution_st *; 52 /** \endcond */ 53 54 struct curandDistributionShift_st { 55 curandDistribution_t probability; 56 curandDistribution_t host_probability; 57 uint shift; 58 uint length; 59 uint host_gen; 60 }; 61 62 alias curandDistributionShift_t = curandDistributionShift_st*; 63 64 struct curandHistogramM2_st { 65 curandHistogramM2V_t V; 66 curandHistogramM2V_t host_V; 67 curandHistogramM2K_t K; 68 curandHistogramM2K_t host_K; 69 uint host_gen; 70 }; 71 72 73 struct curandDistributionM2Shift_st { 74 curandHistogramM2_t histogram; 75 curandHistogramM2_t host_histogram; 76 uint shift; 77 uint length; 78 uint host_gen; 79 }; 80 81 struct curandDiscreteDistribution_st { 82 curandDiscreteDistribution_t self_host_ptr; 83 curandDistributionM2Shift_t M2; 84 curandDistributionM2Shift_t host_M2; 85 double stddev; 86 double mean; 87 curandMethod_t method; 88 uint host_gen; 89 }; 90 91 alias curandDistributionM2Shift_t = curandDistributionM2Shift_st*; 92 alias curandHistogramM2_t = curandHistogramM2_st*; 93 94 // curand.h 95 96 /** 97 * CURAND function call status types 98 */ 99 alias curandStatus = int; 100 enum : curandStatus { 101 CURAND_STATUS_SUCCESS = 0, ///< No errors 102 CURAND_STATUS_VERSION_MISMATCH = 100, ///< Header file and linked library version do not match 103 CURAND_STATUS_NOT_INITIALIZED = 101, ///< Generator not initialized 104 CURAND_STATUS_ALLOCATION_FAILED = 102, ///< Memory allocation failed 105 CURAND_STATUS_TYPE_ERROR = 103, ///< Generator is wrong type 106 CURAND_STATUS_OUT_OF_RANGE = 104, ///< Argument out of range 107 CURAND_STATUS_LENGTH_NOT_MULTIPLE = 105, ///< Length requested is not a multple of dimension 108 CURAND_STATUS_DOUBLE_PRECISION_REQUIRED = 106, ///< GPU does not have double precision required by MRG32k3a 109 CURAND_STATUS_LAUNCH_FAILURE = 201, ///< Kernel launch failure 110 CURAND_STATUS_PREEXISTING_FAILURE = 202, ///< Preexisting failure on library entry 111 CURAND_STATUS_INITIALIZATION_FAILED = 203, ///< Initialization of CUDA failed 112 CURAND_STATUS_ARCH_MISMATCH = 204, ///< Architecture mismatch, GPU does not support requested feature 113 CURAND_STATUS_INTERNAL_ERROR = 999 ///< Internal library error 114 } 115 116 /* 117 * CURAND function call status types 118 */ 119 /** \cond UNHIDE_TYPEDEFS */ 120 alias curandStatus_t = curandStatus; 121 /** \endcond */ 122 123 /** 124 * CURAND generator types 125 */ 126 alias curandRngType = int; 127 enum : curandRngType { 128 CURAND_RNG_TEST = 0, 129 CURAND_RNG_PSEUDO_DEFAULT = 100, ///< Default pseudorandom generator 130 CURAND_RNG_PSEUDO_XORWOW = 101, ///< XORWOW pseudorandom generator 131 CURAND_RNG_PSEUDO_MRG32K3A = 121, ///< MRG32k3a pseudorandom generator 132 CURAND_RNG_PSEUDO_MTGP32 = 141, ///< Mersenne Twister MTGP32 pseudorandom generator 133 CURAND_RNG_PSEUDO_MT19937 = 142, ///< Mersenne Twister MT19937 pseudorandom generator 134 CURAND_RNG_PSEUDO_PHILOX4_32_10 = 161, ///< PHILOX-4x32-10 pseudorandom generator 135 CURAND_RNG_QUASI_DEFAULT = 200, ///< Default quasirandom generator 136 CURAND_RNG_QUASI_SOBOL32 = 201, ///< Sobol32 quasirandom generator 137 CURAND_RNG_QUASI_SCRAMBLED_SOBOL32 = 202, ///< Scrambled Sobol32 quasirandom generator 138 CURAND_RNG_QUASI_SOBOL64 = 203, ///< Sobol64 quasirandom generator 139 CURAND_RNG_QUASI_SCRAMBLED_SOBOL64 = 204 ///< Scrambled Sobol64 quasirandom generator 140 } 141 142 /* 143 * CURAND generator types 144 */ 145 /** \cond UNHIDE_TYPEDEFS */ 146 alias curandRngType_t = curandRngType; 147 /** \endcond */ 148 149 /** 150 * CURAND ordering of results in memory 151 */ 152 alias curandOrdering = int; 153 enum : curandOrdering { 154 CURAND_ORDERING_PSEUDO_BEST = 100, ///< Best ordering for pseudorandom results 155 CURAND_ORDERING_PSEUDO_DEFAULT = 101, ///< Specific default 4096 thread sequence for pseudorandom results 156 CURAND_ORDERING_PSEUDO_SEEDED = 102, ///< Specific seeding pattern for fast lower quality pseudorandom results 157 CURAND_ORDERING_QUASI_DEFAULT = 201 ///< Specific n-dimensional ordering for quasirandom results 158 } 159 160 /* 161 * CURAND ordering of results in memory 162 */ 163 /** \cond UNHIDE_TYPEDEFS */ 164 alias curandOrdering_t = curandOrdering; 165 /** \endcond */ 166 167 /** 168 * CURAND choice of direction vector set 169 */ 170 alias curandDirectionVectorSet = int; 171 enum : curandDirectionVectorSet { 172 CURAND_DIRECTION_VECTORS_32_JOEKUO6 = 101, ///< Specific set of 32-bit direction vectors generated from polynomials recommended by S. Joe and F. Y. Kuo, for up to 20,000 dimensions 173 CURAND_SCRAMBLED_DIRECTION_VECTORS_32_JOEKUO6 = 102, ///< Specific set of 32-bit direction vectors generated from polynomials recommended by S. Joe and F. Y. Kuo, for up to 20,000 dimensions, and scrambled 174 CURAND_DIRECTION_VECTORS_64_JOEKUO6 = 103, ///< Specific set of 64-bit direction vectors generated from polynomials recommended by S. Joe and F. Y. Kuo, for up to 20,000 dimensions 175 CURAND_SCRAMBLED_DIRECTION_VECTORS_64_JOEKUO6 = 104 ///< Specific set of 64-bit direction vectors generated from polynomials recommended by S. Joe and F. Y. Kuo, for up to 20,000 dimensions, and scrambled 176 } 177 178 /* 179 * CURAND choice of direction vector set 180 */ 181 /** \cond UNHIDE_TYPEDEFS */ 182 alias curandDirectionVectorSet_t = curandDirectionVectorSet; 183 /** \endcond */ 184 185 /** 186 * CURAND array of 32-bit direction vectors 187 */ 188 /** \cond UNHIDE_TYPEDEFS */ 189 alias curandDirectionVectors32_t = uint[32]; 190 /** \endcond */ 191 192 /** 193 * CURAND array of 64-bit direction vectors 194 */ 195 /** \cond UNHIDE_TYPEDEFS */ 196 alias curandDirectionVectors64_t = ulong[64]; 197 /** \endcond **/ 198 199 /** 200 * CURAND generator (opaque) 201 */ 202 struct curandGenerator_st; 203 204 /** 205 * CURAND generator 206 */ 207 /** \cond UNHIDE_TYPEDEFS */ 208 alias curandGenerator_t = curandGenerator_st *; 209 /** \endcond */ 210 211 /* 212 * CURAND METHOD 213 */ 214 /** \cond UNHIDE_ENUMS */ 215 alias curandMethod = int; 216 enum : curandMethod { 217 CURAND_CHOOSE_BEST = 0, // choose best depends on args 218 CURAND_ITR = 1, 219 CURAND_KNUTH = 2, 220 CURAND_HITR = 3, 221 CURAND_M1 = 4, 222 CURAND_M2 = 5, 223 CURAND_BINARY_SEARCH = 6, 224 CURAND_DISCRETE_GAUSS = 7, 225 CURAND_REJECTION = 8, 226 CURAND_DEVICE_API = 9, 227 CURAND_FAST_REJECTION = 10, 228 CURAND_3RD = 11, 229 CURAND_DEFINITION = 12, 230 CURAND_POISSON = 13 231 } 232 233 alias curandMethod_t = curandMethod; 234 235 236 extern(System) nothrow { 237 238 } 239 240 241 extern(System) @nogc nothrow { 242 243 alias da_curandCreateGenerator = curandStatus_t function(curandGenerator_t *generator, curandRngType_t rng_type); 244 alias da_curandCreateGeneratorHost = curandStatus_t function(curandGenerator_t *generator, curandRngType_t rng_type); 245 alias da_curandDestroyGenerator = curandStatus_t function(curandGenerator_t generator); 246 alias da_curandGetVersion = curandStatus_t function(int *pVersion); 247 alias da_curandGetProperty = curandStatus_t function(libraryPropertyType type, int *value); 248 alias da_curandSetStream = curandStatus_t function(curandGenerator_t generator, cudaStream_t stream); 249 alias da_curandSetPseudoRandomGeneratorSeed = curandStatus_t function(curandGenerator_t generator, ulong seed); 250 alias da_curandSetGeneratorOffset = curandStatus_t function(curandGenerator_t generator, ulong offset); 251 alias da_curandSetGeneratorOrdering = curandStatus_t function(curandGenerator_t generator, curandOrdering_t order); 252 alias da_curandSetQuasiRandomGeneratorDimensions = curandStatus_t function(curandGenerator_t generator, uint num_dimensions); 253 alias da_curandGenerate = curandStatus_t function(curandGenerator_t generator, uint *outputPtr, size_t num); 254 alias da_curandGenerateLongLong = curandStatus_t function(curandGenerator_t generator, ulong *outputPtr, size_t num); 255 alias da_curandGenerateUniform = curandStatus_t function(curandGenerator_t generator, float *outputPtr, size_t num); 256 alias da_curandGenerateUniformDouble = curandStatus_t function(curandGenerator_t generator, double *outputPtr, size_t num); 257 alias da_curandGenerateNormal = curandStatus_t function(curandGenerator_t generator, float *outputPtr, size_t n, float mean, float stddev); 258 alias da_curandGenerateNormalDouble = curandStatus_t function(curandGenerator_t generator, double *outputPtr, size_t n, double mean, double stddev); 259 alias da_curandGenerateLogNormal = curandStatus_t function(curandGenerator_t generator, float *outputPtr, size_t n, float mean, float stddev); 260 alias da_curandGenerateLogNormalDouble = curandStatus_t function(curandGenerator_t generator, double *outputPtr,size_t n, double mean, double stddev); 261 alias da_curandCreatePoissonDistribution = curandStatus_t function(double lambda, curandDiscreteDistribution_t *discrete_distribution); 262 alias da_curandDestroyDistribution = curandStatus_t function(curandDiscreteDistribution_t discrete_distribution); 263 alias da_curandGeneratePoisson = curandStatus_t function(curandGenerator_t generator, uint *outputPtr,size_t n, double lambda); 264 alias da_curandGeneratePoissonMethod = curandStatus_t function(curandGenerator_t generator, uint *outputPtr,size_t n, double lambda, curandMethod_t method); 265 //alias da_curandGenerateBinomial = curandStatus_t function(curandGenerator_t generator, uint *outputPtr,size_t num, uint n, double p); 266 //alias da_curandGenerateBinomialMethod = curandStatus_t function(curandGenerator_t generator,uint *outputPtr,size_t num, uint n, double p,curandMethod_t method); 267 alias da_curandGenerateSeeds = curandStatus_t function(curandGenerator_t generator); 268 alias da_curandGetDirectionVectors32 = curandStatus_t function(curandDirectionVectors32_t *[] vectors, curandDirectionVectorSet_t set); 269 alias da_curandGetScrambleConstants32 = curandStatus_t function(uint * * constants); 270 alias da_curandGetDirectionVectors64 = curandStatus_t function(curandDirectionVectors64_t *[] vectors, curandDirectionVectorSet_t set); 271 alias da_curandGetScrambleConstants64 = curandStatus_t function(ulong * * constants); 272 273 } 274 275 __gshared 276 { 277 da_curandCreateGenerator curandCreateGenerator; 278 da_curandCreateGeneratorHost curandCreateGeneratorHost; 279 da_curandDestroyGenerator curandDestroyGenerator; 280 da_curandGetVersion curandGetVersion; 281 da_curandGetProperty curandGetProperty; 282 da_curandSetStream curandSetStream; 283 da_curandSetPseudoRandomGeneratorSeed curandSetPseudoRandomGeneratorSeed; 284 da_curandSetGeneratorOffset curandSetGeneratorOffset; 285 da_curandSetGeneratorOrdering curandSetGeneratorOrdering; 286 da_curandSetQuasiRandomGeneratorDimensions curandSetQuasiRandomGeneratorDimensions; 287 da_curandGenerate curandGenerate; 288 da_curandGenerateLongLong curandGenerateLongLong; 289 da_curandGenerateUniform curandGenerateUniform; 290 da_curandGenerateUniformDouble curandGenerateUniformDouble; 291 da_curandGenerateNormal curandGenerateNormal; 292 da_curandGenerateNormalDouble curandGenerateNormalDouble; 293 da_curandGenerateLogNormal curandGenerateLogNormal; 294 da_curandGenerateLogNormalDouble curandGenerateLogNormalDouble; 295 da_curandCreatePoissonDistribution curandCreatePoissonDistribution; 296 da_curandDestroyDistribution curandDestroyDistribution; 297 da_curandGeneratePoisson curandGeneratePoisson; 298 da_curandGeneratePoissonMethod curandGeneratePoissonMethod; 299 //da_curandGenerateBinomial curandGenerateBinomial; 300 //da_curandGenerateBinomialMethod curandGenerateBinomialMethod; 301 da_curandGenerateSeeds curandGenerateSeeds; 302 da_curandGetDirectionVectors32 curandGetDirectionVectors32; 303 da_curandGetScrambleConstants32 curandGetScrambleConstants32; 304 da_curandGetDirectionVectors64 curandGetDirectionVectors64; 305 da_curandGetScrambleConstants64 curandGetScrambleConstants64; 306 } 307 308 // Runtime API loader 309 class DerelictCuRANDLoader : SharedLibLoader 310 { 311 protected 312 { 313 override void loadSymbols() 314 { 315 bindFunc(cast(void**)&curandCreateGenerator, "curandCreateGenerator"); 316 bindFunc(cast(void**)&curandCreateGeneratorHost, "curandCreateGeneratorHost"); 317 bindFunc(cast(void**)&curandDestroyGenerator, "curandDestroyGenerator"); 318 bindFunc(cast(void**)&curandGetVersion, "curandGetVersion"); 319 bindFunc(cast(void**)&curandGetProperty, "curandGetProperty"); 320 bindFunc(cast(void**)&curandSetStream, "curandSetStream"); 321 bindFunc(cast(void**)&curandSetPseudoRandomGeneratorSeed, "curandSetPseudoRandomGeneratorSeed"); 322 bindFunc(cast(void**)&curandSetGeneratorOffset, "curandSetGeneratorOffset"); 323 bindFunc(cast(void**)&curandSetGeneratorOrdering, "curandSetGeneratorOrdering"); 324 bindFunc(cast(void**)&curandSetQuasiRandomGeneratorDimensions, "curandSetQuasiRandomGeneratorDimensions"); 325 bindFunc(cast(void**)&curandGenerate, "curandGenerate"); 326 bindFunc(cast(void**)&curandGenerateLongLong, "curandGenerateLongLong"); 327 bindFunc(cast(void**)&curandGenerateUniform, "curandGenerateUniform"); 328 bindFunc(cast(void**)&curandGenerateUniformDouble, "curandGenerateUniformDouble"); 329 bindFunc(cast(void**)&curandGenerateNormal, "curandGenerateNormal"); 330 bindFunc(cast(void**)&curandGenerateNormalDouble, "curandGenerateNormalDouble"); 331 bindFunc(cast(void**)&curandGenerateLogNormal, "curandGenerateLogNormal"); 332 bindFunc(cast(void**)&curandGenerateLogNormalDouble, "curandGenerateLogNormalDouble"); 333 bindFunc(cast(void**)&curandCreatePoissonDistribution, "curandCreatePoissonDistribution"); 334 bindFunc(cast(void**)&curandDestroyDistribution, "curandDestroyDistribution"); 335 bindFunc(cast(void**)&curandGeneratePoisson, "curandGeneratePoisson"); 336 bindFunc(cast(void**)&curandGeneratePoissonMethod, "curandGeneratePoissonMethod"); 337 //bindFunc(cast(void**)&curandGenerateBinomial, "curandGenerateBinomial"); 338 //bindFunc(cast(void**)&curandGenerateBinomialMethod, "curandGenerateBinomialMethod"); 339 bindFunc(cast(void**)&curandGenerateSeeds, "curandGenerateSeeds"); 340 bindFunc(cast(void**)&curandGetDirectionVectors32, "curandGetDirectionVectors32"); 341 bindFunc(cast(void**)&curandGetScrambleConstants32, "curandGetScrambleConstants32"); 342 bindFunc(cast(void**)&curandGetDirectionVectors64, "curandGetDirectionVectors64"); 343 bindFunc(cast(void**)&curandGetScrambleConstants64, "curandGetScrambleConstants64"); 344 } 345 } 346 347 public 348 { 349 this() 350 { 351 super(libNames); 352 } 353 } 354 } 355 356 __gshared DerelictCuRANDLoader DerelictCuRAND; 357 358 shared static this() 359 { 360 DerelictCuRAND = new DerelictCuRANDLoader(); 361 }