Random Number Generation

Runtime supports the delivery of built-in system tasks for 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.

Use aclrtRandomNumAsync to execute the random number generation task. The sample code is as follows: For the complete sample code, click here.

 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 device memory.
    void *devOutput = NULL;
    ret = aclrtMalloc(&devOutput, size, ACL_MEM_MALLOC_NORMAL_ONLY);
    // Prepare host data.
    void *hostOutput = malloc(size);
    // Allocate 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;
}