Random number generation (Random)
In addition to delivering kernel execution tasks, Runtime also provides the function of delivering built-in system tasks for reduction and random number generation. (The difference between system tasks and kernel tasks is that system tasks do not require you to provide execution code.) System tasks can be delivered to a stream for asynchronous execution, and they also comply with the rule of preserving the order of tasks on the same stream.
The aclrtReduceAsync API can be used to deliver a task for performing the reduction operation. The sample code is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | aclInit(NULL); aclrtSetDevice(0); aclrtStream stream; aclrtCreateStream(&stream); // Prepare host data. const int count = 4; float hostInput[4] = {1.0, 2.0, 3.0, 4.0}; float hostOutput[4] = {0, 0, 0, 0}; size_t size = count * sizeof(float); // Allocate the device memory. void *devInput = NULL; void *devOutput = NULL; aclrtMalloc(&devInput, size, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc(&devOutput, size, ACL_MEM_MALLOC_HUGE_FIRST); // Copy data to the device. aclrtMemcpy(devInput, size, hostInput, size, ACL_MEMCPY_HOST_TO_DEVICE); aclrtMemcpy(devOutput, size, hostInput, size, ACL_MEMCPY_HOST_TO_DEVICE); // Call aclrtReduceAsync. aclrtReduceAsync(devOutput, devInput, size, ACL_RT_MEMCPY_SDMA_AUTOMATIC_SUM, // Reduction type. ACL_FLOAT, // Data type. stream, NULL); // Synchronize the stream. aclrtSynchronizeStream(stream); // Copy back the result. aclrtMemcpy(hostOutput, size, devOutput, size, ACL_MEMCPY_DEVICE_TO_HOST); for (int i = 0; i < count; i++) { printf("Reduce SUM result[%d] = %f\n", i, hostOutput[i]); } /* The expected result is as follows: Reduce SUM result[0] = 2.000000 Reduce SUM result[1] = 4.000000 Reduce SUM result[2] = 6.000000 Reduce SUM result[3] = 8.000000 */ // Free resources. aclrtFree(devInput); aclrtFree(devOutput); aclrtDestroyStream(stream); aclrtResetDeviceForce(0); aclFinalize(); |
Use aclrtRandomNumAsync to execute the random number generation task. The sample code is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | aclError NormalFloatAsync( float mean, float stddev, uint64_t seed, uint64_t num, void *counterDevAddr, void *devOutput, aclrtStream stream) { aclrtRandomNumTaskInfo taskInfo = {}; taskInfo.dataType = ACL_FLOAT; taskInfo.randomNumFuncParaInfo.funcType = ACL_RT_RANDOM_NUM_FUNC_TYPE_NORMAL_DIS; taskInfo.randomParaAddr = NULL; taskInfo.randomCounterAddr = counterDevAddr; taskInfo.randomResultAddr = devOutput; memcpy(taskInfo.randomNumFuncParaInfo.paramInfo.normalDisInfo.mean.valueOrAddr, &mean, sizeof(float)); taskInfo.randomNumFuncParaInfo.paramInfo.normalDisInfo.mean.size = sizeof(float); taskInfo.randomNumFuncParaInfo.paramInfo.normalDisInfo.mean.isAddr = 0; memcpy(taskInfo.randomNumFuncParaInfo.paramInfo.normalDisInfo.stddev.valueOrAddr, &stddev, sizeof(float)); taskInfo.randomNumFuncParaInfo.paramInfo.normalDisInfo.stddev.size = sizeof(float); taskInfo.randomNumFuncParaInfo.paramInfo.normalDisInfo.stddev.isAddr = 0; memcpy(taskInfo.randomSeed.valueOrAddr, &seed, sizeof(uint64_t)); taskInfo.randomSeed.size = sizeof(uint64_t); taskInfo.randomSeed.isAddr = 0; memcpy(taskInfo.randomNum.valueOrAddr, &num, sizeof(uint64_t)); taskInfo.randomNum.size = sizeof(uint64_t); taskInfo.randomNum.isAddr = 0; return aclrtRandomNumAsync(&taskInfo, stream, NULL); } int main() { aclError ret; // Initialize the ACL. ret = aclInit(NULL); ret = aclrtSetDevice(0); aclrtStream stream; ret = aclrtCreateStream(&stream); uint64_t num = 128; size_t size = num * sizeof(uint64_t); // Allocate sufficient memory. // Allocate the device memory. void *devOutput = NULL; ret = aclrtMalloc(&devOutput, size, ACL_MEM_MALLOC_NORMAL_ONLY); // Prepare host data. void *hostOutput = malloc(size); // Allocate the device memory (16 bytes required) for storing the random number status counter. void *counterAddr = NULL; ret = aclrtMalloc((void **)&counterAddr, 16, ACL_MEM_MALLOC_NORMAL_ONLY); float mean = 3.0; float stddev = 2.0; ret =NormalFloatAsync(mean, stddev, 0, num, counterAddr, devOutput, stream); // Synchronize the stream. aclrtSynchronizeStream(stream); // Copy back the result. aclrtMemcpy(hostOutput, size, devOutput, size, ACL_MEMCPY_DEVICE_TO_HOST); // Free resources. free(hostOutput); aclrtFree(devOutput); aclrtFree(counterAddr); aclrtDestroyStream(stream); aclrtResetDeviceForce(0); aclFinalize(); return 0; } |
Parent topic: Dedicated Accelerator