1484543d1Sopenharmony_ci/*
2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License.
5484543d1Sopenharmony_ci * You may obtain a copy of the License at
6484543d1Sopenharmony_ci *
7484543d1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8484543d1Sopenharmony_ci *
9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and
13484543d1Sopenharmony_ci * limitations under the License.
14484543d1Sopenharmony_ci */
15484543d1Sopenharmony_ci
16484543d1Sopenharmony_ci#include <random>
17484543d1Sopenharmony_ci
18484543d1Sopenharmony_ci#include "ffrt_inner.h"
19484543d1Sopenharmony_ci#include "common.h"
20484543d1Sopenharmony_ci
21484543d1Sopenharmony_cistatic constexpr uint64_t sz = 30; // 该值越大任务平均可并行度越大(平均并发度=sz/9)
22484543d1Sopenharmony_cistatic constexpr uint64_t iter = 1000000; // 该值越大迭代次数越多(减少测量误差)
23484543d1Sopenharmony_cistatic constexpr uint64_t depth = 10; // 该值越大子任务平均粒度越大(任务完成时间为泊松分布)(单位:微秒)
24484543d1Sopenharmony_ci
25484543d1Sopenharmony_cistatic inline uint64_t func(uint64_t x, uint64_t y)
26484543d1Sopenharmony_ci{
27484543d1Sopenharmony_ci    std::mt19937_64 g(x - y);
28484543d1Sopenharmony_ci    uint64_t target = g() % (depth * 20);
29484543d1Sopenharmony_ci    uint64_t acc = 0;
30484543d1Sopenharmony_ci    while (acc % (depth * 20) != target) {
31484543d1Sopenharmony_ci        acc ^= g();
32484543d1Sopenharmony_ci    }
33484543d1Sopenharmony_ci    return acc;
34484543d1Sopenharmony_ci}
35484543d1Sopenharmony_ci
36484543d1Sopenharmony_cistatic inline void GenerateIndexes(std::mt19937_64& rnd, uint64_t(idx)[3])
37484543d1Sopenharmony_ci{
38484543d1Sopenharmony_ci    bool duplicate = true;
39484543d1Sopenharmony_ci    while (duplicate) {
40484543d1Sopenharmony_ci        duplicate = false;
41484543d1Sopenharmony_ci        for (uint64_t i = 0; i < 3; i++) {
42484543d1Sopenharmony_ci            idx[i] = rnd() % sz;
43484543d1Sopenharmony_ci            for (uint64_t z = 0; z < i; z++) {
44484543d1Sopenharmony_ci                if (idx[z] == idx[i]) {
45484543d1Sopenharmony_ci                    duplicate = true;
46484543d1Sopenharmony_ci                }
47484543d1Sopenharmony_ci            }
48484543d1Sopenharmony_ci        }
49484543d1Sopenharmony_ci    }
50484543d1Sopenharmony_ci}
51484543d1Sopenharmony_ci
52484543d1Sopenharmony_cistatic uint64_t BenchmarkNative()
53484543d1Sopenharmony_ci{
54484543d1Sopenharmony_ci    uint64_t* arr = new uint64_t[sz];
55484543d1Sopenharmony_ci    std::mt19937_64 rnd(0);
56484543d1Sopenharmony_ci    // initialize the array
57484543d1Sopenharmony_ci    for (uint64_t i = 0; i < sz; i++) {
58484543d1Sopenharmony_ci        arr[i] = rnd();
59484543d1Sopenharmony_ci    }
60484543d1Sopenharmony_ci
61484543d1Sopenharmony_ci    // do computation randomly
62484543d1Sopenharmony_ci    TIME_BEGIN(t);
63484543d1Sopenharmony_ci    for (uint64_t i = 0; i < iter; i++) {
64484543d1Sopenharmony_ci        // generate 3 different indexes
65484543d1Sopenharmony_ci        uint64_t idx[3] = {};
66484543d1Sopenharmony_ci        GenerateIndexes(rnd, idx);
67484543d1Sopenharmony_ci
68484543d1Sopenharmony_ci        // submit a task
69484543d1Sopenharmony_ci        arr[idx[2]] = func(arr[idx[0]], arr[idx[1]]);
70484543d1Sopenharmony_ci    }
71484543d1Sopenharmony_ci    TIME_END_INFO(t, "benchmark_native");
72484543d1Sopenharmony_ci
73484543d1Sopenharmony_ci    // calculate FNV hash of the array
74484543d1Sopenharmony_ci    uint64_t hash = 14695981039346656037ULL;
75484543d1Sopenharmony_ci    for (uint64_t i = 0; i < sz; i++) {
76484543d1Sopenharmony_ci        hash = (hash * 1099511628211ULL) ^ arr[i];
77484543d1Sopenharmony_ci    }
78484543d1Sopenharmony_ci    delete[] arr;
79484543d1Sopenharmony_ci    return hash;
80484543d1Sopenharmony_ci}
81484543d1Sopenharmony_ci
82484543d1Sopenharmony_cistatic uint64_t BenchmarkFFRT()
83484543d1Sopenharmony_ci{
84484543d1Sopenharmony_ci    uint64_t* arr = new uint64_t[sz];
85484543d1Sopenharmony_ci    std::mt19937_64 rnd(0);
86484543d1Sopenharmony_ci    // initialize the array
87484543d1Sopenharmony_ci    for (uint64_t i = 0; i < sz; i++) {
88484543d1Sopenharmony_ci        arr[i] = rnd();
89484543d1Sopenharmony_ci    }
90484543d1Sopenharmony_ci    // do computation randomly
91484543d1Sopenharmony_ci    TIME_BEGIN(t);
92484543d1Sopenharmony_ci    for (uint64_t i = 0; i < iter; i++) {
93484543d1Sopenharmony_ci        // generate 3 different indexes
94484543d1Sopenharmony_ci        uint64_t idx[3] = {};
95484543d1Sopenharmony_ci        GenerateIndexes(rnd, idx);
96484543d1Sopenharmony_ci
97484543d1Sopenharmony_ci        // submit a task
98484543d1Sopenharmony_ci        ffrt::submit([idx, &arr]() { arr[idx[2]] = func(arr[idx[0]], arr[idx[1]]); }, {&arr[idx[0]], &arr[idx[1]]},
99484543d1Sopenharmony_ci            {&arr[idx[2]]});
100484543d1Sopenharmony_ci    }
101484543d1Sopenharmony_ci    ffrt::wait();
102484543d1Sopenharmony_ci    TIME_END_INFO(t, "benchmark_ffrt");
103484543d1Sopenharmony_ci
104484543d1Sopenharmony_ci    // calculate FNV hash of the array
105484543d1Sopenharmony_ci    uint64_t hash = 14695981039346656037ULL;
106484543d1Sopenharmony_ci    for (uint64_t i = 0; i < sz; i++) {
107484543d1Sopenharmony_ci        hash = (hash * 1099511628211ULL) ^ arr[i];
108484543d1Sopenharmony_ci    }
109484543d1Sopenharmony_ci    delete[] arr;
110484543d1Sopenharmony_ci    return hash;
111484543d1Sopenharmony_ci}
112484543d1Sopenharmony_ci
113484543d1Sopenharmony_ciint main()
114484543d1Sopenharmony_ci{
115484543d1Sopenharmony_ci    GetEnvs();
116484543d1Sopenharmony_ci    BenchmarkNative();
117484543d1Sopenharmony_ci    BenchmarkFFRT();
118484543d1Sopenharmony_ci}