1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <random>
17 
18 #include "ffrt_inner.h"
19 #include "common.h"
20 
21 static constexpr uint64_t sz = 30; // 该值越大任务平均可并行度越大(平均并发度=sz/9)
22 static constexpr uint64_t iter = 1000000; // 该值越大迭代次数越多(减少测量误差)
23 static constexpr uint64_t depth = 10; // 该值越大子任务平均粒度越大(任务完成时间为泊松分布)(单位:微秒)
24 
func(uint64_t x,uint64_t y)25 static inline uint64_t func(uint64_t x, uint64_t y)
26 {
27     std::mt19937_64 g(x - y);
28     uint64_t target = g() % (depth * 20);
29     uint64_t acc = 0;
30     while (acc % (depth * 20) != target) {
31         acc ^= g();
32     }
33     return acc;
34 }
35 
GenerateIndexes(std::mt19937_64 & rnd,uint64_t (idx)[3])36 static inline void GenerateIndexes(std::mt19937_64& rnd, uint64_t(idx)[3])
37 {
38     bool duplicate = true;
39     while (duplicate) {
40         duplicate = false;
41         for (uint64_t i = 0; i < 3; i++) {
42             idx[i] = rnd() % sz;
43             for (uint64_t z = 0; z < i; z++) {
44                 if (idx[z] == idx[i]) {
45                     duplicate = true;
46                 }
47             }
48         }
49     }
50 }
51 
BenchmarkNative()52 static uint64_t BenchmarkNative()
53 {
54     uint64_t* arr = new uint64_t[sz];
55     std::mt19937_64 rnd(0);
56     // initialize the array
57     for (uint64_t i = 0; i < sz; i++) {
58         arr[i] = rnd();
59     }
60 
61     // do computation randomly
62     TIME_BEGIN(t);
63     for (uint64_t i = 0; i < iter; i++) {
64         // generate 3 different indexes
65         uint64_t idx[3] = {};
66         GenerateIndexes(rnd, idx);
67 
68         // submit a task
69         arr[idx[2]] = func(arr[idx[0]], arr[idx[1]]);
70     }
71     TIME_END_INFO(t, "benchmark_native");
72 
73     // calculate FNV hash of the array
74     uint64_t hash = 14695981039346656037ULL;
75     for (uint64_t i = 0; i < sz; i++) {
76         hash = (hash * 1099511628211ULL) ^ arr[i];
77     }
78     delete[] arr;
79     return hash;
80 }
81 
BenchmarkFFRT()82 static uint64_t BenchmarkFFRT()
83 {
84     uint64_t* arr = new uint64_t[sz];
85     std::mt19937_64 rnd(0);
86     // initialize the array
87     for (uint64_t i = 0; i < sz; i++) {
88         arr[i] = rnd();
89     }
90     // do computation randomly
91     TIME_BEGIN(t);
92     for (uint64_t i = 0; i < iter; i++) {
93         // generate 3 different indexes
94         uint64_t idx[3] = {};
95         GenerateIndexes(rnd, idx);
96 
97         // submit a task
98         ffrt::submit([idx, &arr]() { arr[idx[2]] = func(arr[idx[0]], arr[idx[1]]); }, {&arr[idx[0]], &arr[idx[1]]},
99             {&arr[idx[2]]});
100     }
101     ffrt::wait();
102     TIME_END_INFO(t, "benchmark_ffrt");
103 
104     // calculate FNV hash of the array
105     uint64_t hash = 14695981039346656037ULL;
106     for (uint64_t i = 0; i < sz; i++) {
107         hash = (hash * 1099511628211ULL) ^ arr[i];
108     }
109     delete[] arr;
110     return hash;
111 }
112 
main()113 int main()
114 {
115     GetEnvs();
116     BenchmarkNative();
117     BenchmarkFFRT();
118 }