xref: /aosp_15_r20/external/sandboxed-api/contrib/pffft/main_pffft_sandboxed.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1*ec63e07aSXin Li // Copyright 2020 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li //     https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li 
15*ec63e07aSXin Li #include <syscall.h>
16*ec63e07aSXin Li 
17*ec63e07aSXin Li #include <cmath>
18*ec63e07aSXin Li #include <cstdio>
19*ec63e07aSXin Li #include <cstdlib>
20*ec63e07aSXin Li #include <cstring>
21*ec63e07aSXin Li #include <ctime>
22*ec63e07aSXin Li 
23*ec63e07aSXin Li #include "pffft_sapi.sapi.h"  // NOLINT(build/include)
24*ec63e07aSXin Li #include "absl/flags/flag.h"
25*ec63e07aSXin Li #include "absl/flags/parse.h"
26*ec63e07aSXin Li #include "absl/log/globals.h"
27*ec63e07aSXin Li #include "absl/log/initialize.h"
28*ec63e07aSXin Li #include "sandboxed_api/vars.h"
29*ec63e07aSXin Li 
30*ec63e07aSXin Li class PffftSapiSandbox : public PffftSandbox {
31*ec63e07aSXin Li  public:
ModifyPolicy(sandbox2::PolicyBuilder *)32*ec63e07aSXin Li   std::unique_ptr<sandbox2::Policy> ModifyPolicy(sandbox2::PolicyBuilder*) {
33*ec63e07aSXin Li     return sandbox2::PolicyBuilder()
34*ec63e07aSXin Li         .AllowStaticStartup()
35*ec63e07aSXin Li         .AllowOpen()
36*ec63e07aSXin Li         .AllowRead()
37*ec63e07aSXin Li         .AllowWrite()
38*ec63e07aSXin Li         .AllowSystemMalloc()
39*ec63e07aSXin Li         .AllowExit()
40*ec63e07aSXin Li         .AllowSyscalls({
41*ec63e07aSXin Li             __NR_futex,
42*ec63e07aSXin Li             __NR_close,
43*ec63e07aSXin Li             __NR_getrusage,
44*ec63e07aSXin Li         })
45*ec63e07aSXin Li         .BuildOrDie();
46*ec63e07aSXin Li   }
47*ec63e07aSXin Li };
48*ec63e07aSXin Li 
49*ec63e07aSXin Li ABSL_FLAG(bool, verbose_output, true, "Whether to display verbose output");
50*ec63e07aSXin Li 
UclockSec()51*ec63e07aSXin Li double UclockSec() { return static_cast<double>(clock()) / CLOCKS_PER_SEC; }
52*ec63e07aSXin Li 
ShowOutput(const char * name,int n,int complex,float flops,float t0,float t1,int max_iter)53*ec63e07aSXin Li void ShowOutput(const char* name, int n, int complex, float flops, float t0,
54*ec63e07aSXin Li                 float t1, int max_iter) {
55*ec63e07aSXin Li   float mflops = flops / 1e6 / (t1 - t0 + 1e-16);
56*ec63e07aSXin Li   if (absl::GetFlag(FLAGS_verbose_output)) {
57*ec63e07aSXin Li     if (flops != -1) {
58*ec63e07aSXin Li       printf("|%9.0f   ", mflops);
59*ec63e07aSXin Li     } else {
60*ec63e07aSXin Li       printf("|      n/a   ");
61*ec63e07aSXin Li     }
62*ec63e07aSXin Li   } else if (flops != -1) {
63*ec63e07aSXin Li     printf("n=%5d, %s %16s : %6.0f MFlops [t=%6.0f ns, %d runs]\n", n,
64*ec63e07aSXin Li            (complex ? "CPLX" : "REAL"), name, mflops,
65*ec63e07aSXin Li            (t1 - t0) / 2 / max_iter * 1e9, max_iter);
66*ec63e07aSXin Li   }
67*ec63e07aSXin Li   fflush(stdout);
68*ec63e07aSXin Li }
69*ec63e07aSXin Li 
PffftMain()70*ec63e07aSXin Li absl::Status PffftMain() {
71*ec63e07aSXin Li   LOG(INFO) << "Initializing sandbox...\n";
72*ec63e07aSXin Li 
73*ec63e07aSXin Li   PffftSapiSandbox sandbox;
74*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(sandbox.Init());
75*ec63e07aSXin Li 
76*ec63e07aSXin Li   PffftApi api(&sandbox);
77*ec63e07aSXin Li 
78*ec63e07aSXin Li   // kTransformSizes is a vector keeping the values by which iterates n, its
79*ec63e07aSXin Li   // value representing the input length. More concrete, n is the number of data
80*ec63e07aSXin Li   // points the caclulus is up to (determinating its accuracy). To show the
81*ec63e07aSXin Li   // performance of Fast-Fourier Transformations the program is testing for
82*ec63e07aSXin Li   // various values of n.
83*ec63e07aSXin Li   constexpr int kTransformSizes[] = {
84*ec63e07aSXin Li       64,      96,  128,  160,  192,  256,  384,  5 * 96,   512,   5 * 128,
85*ec63e07aSXin Li       3 * 256, 800, 1024, 2048, 2400, 4096, 8192, 9 * 1024, 16384, 32768};
86*ec63e07aSXin Li 
87*ec63e07aSXin Li   for (int complex : {0, 1}) {
88*ec63e07aSXin Li     for (int n : kTransformSizes) {
89*ec63e07aSXin Li       const int n_float = n * (complex ? 2 : 1);
90*ec63e07aSXin Li       int n_bytes = n_float * sizeof(float);
91*ec63e07aSXin Li 
92*ec63e07aSXin Li       std::vector<float> work(2 * n_float + 15, 0.0);
93*ec63e07aSXin Li       sapi::v::Array<float> work_array(&work[0], work.size());
94*ec63e07aSXin Li 
95*ec63e07aSXin Li       std::vector<float> x(n_bytes, 0.0);
96*ec63e07aSXin Li       sapi::v::Array<float> x_array(&x[0], x.size());
97*ec63e07aSXin Li 
98*ec63e07aSXin Li       std::vector<float> y(n_bytes, 0.0);
99*ec63e07aSXin Li       sapi::v::Array<float> y_array(&y[0], y.size());
100*ec63e07aSXin Li 
101*ec63e07aSXin Li       std::vector<float> z(n_bytes, 0.0);
102*ec63e07aSXin Li       sapi::v::Array<float> z_array(&z[0], z.size());
103*ec63e07aSXin Li 
104*ec63e07aSXin Li       double t0;
105*ec63e07aSXin Li       double t1;
106*ec63e07aSXin Li       double flops;
107*ec63e07aSXin Li 
108*ec63e07aSXin Li       int max_iter = 5120000 / n * 4;
109*ec63e07aSXin Li 
110*ec63e07aSXin Li       for (int k = 0; k < n_float; ++k) {
111*ec63e07aSXin Li         x[k] = 0;
112*ec63e07aSXin Li       }
113*ec63e07aSXin Li 
114*ec63e07aSXin Li       // FFTPack benchmark
115*ec63e07aSXin Li       {
116*ec63e07aSXin Li         // SIMD_SZ == 4 (returning value of pffft_simd_size())
117*ec63e07aSXin Li         int simd_size_iter = max_iter / 4;
118*ec63e07aSXin Li 
119*ec63e07aSXin Li         if (simd_size_iter == 0) simd_size_iter = 1;
120*ec63e07aSXin Li         if (complex) {
121*ec63e07aSXin Li           SAPI_RETURN_IF_ERROR(api.cffti(n, work_array.PtrBoth()));
122*ec63e07aSXin Li         } else {
123*ec63e07aSXin Li           SAPI_RETURN_IF_ERROR(api.rffti(n, work_array.PtrBoth()));
124*ec63e07aSXin Li         }
125*ec63e07aSXin Li         t0 = UclockSec();
126*ec63e07aSXin Li 
127*ec63e07aSXin Li         for (int iter = 0; iter < simd_size_iter; ++iter) {
128*ec63e07aSXin Li           if (complex) {
129*ec63e07aSXin Li             SAPI_RETURN_IF_ERROR(
130*ec63e07aSXin Li                 api.cfftf(n, x_array.PtrBoth(), work_array.PtrBoth()));
131*ec63e07aSXin Li             SAPI_RETURN_IF_ERROR(
132*ec63e07aSXin Li                 api.cfftb(n, x_array.PtrBoth(), work_array.PtrBoth()));
133*ec63e07aSXin Li           } else {
134*ec63e07aSXin Li             SAPI_RETURN_IF_ERROR(
135*ec63e07aSXin Li                 api.rfftf(n, x_array.PtrBoth(), work_array.PtrBoth()));
136*ec63e07aSXin Li             SAPI_RETURN_IF_ERROR(
137*ec63e07aSXin Li                 api.rfftb(n, x_array.PtrBoth(), work_array.PtrBoth()));
138*ec63e07aSXin Li           }
139*ec63e07aSXin Li         }
140*ec63e07aSXin Li         t1 = UclockSec();
141*ec63e07aSXin Li 
142*ec63e07aSXin Li         flops = (simd_size_iter * 2) *
143*ec63e07aSXin Li                 ((complex ? 5 : 2.5) * static_cast<double>(n) *
144*ec63e07aSXin Li                  log(static_cast<double>(n)) / M_LN2);
145*ec63e07aSXin Li         ShowOutput("FFTPack", n, complex, flops, t0, t1, simd_size_iter);
146*ec63e07aSXin Li       }
147*ec63e07aSXin Li 
148*ec63e07aSXin Li       // PFFFT benchmark
149*ec63e07aSXin Li       {
150*ec63e07aSXin Li         SAPI_ASSIGN_OR_RETURN(
151*ec63e07aSXin Li             PFFFT_Setup * s,
152*ec63e07aSXin Li             api.pffft_new_setup(n, complex ? PFFFT_COMPLEX : PFFFT_REAL));
153*ec63e07aSXin Li 
154*ec63e07aSXin Li         sapi::v::RemotePtr s_reg(s);
155*ec63e07aSXin Li 
156*ec63e07aSXin Li         t0 = UclockSec();
157*ec63e07aSXin Li         for (int iter = 0; iter < max_iter; ++iter) {
158*ec63e07aSXin Li           SAPI_RETURN_IF_ERROR(
159*ec63e07aSXin Li               api.pffft_transform(&s_reg, x_array.PtrBoth(), z_array.PtrBoth(),
160*ec63e07aSXin Li                                   y_array.PtrBoth(), PFFFT_FORWARD));
161*ec63e07aSXin Li           SAPI_RETURN_IF_ERROR(
162*ec63e07aSXin Li               api.pffft_transform(&s_reg, x_array.PtrBoth(), z_array.PtrBoth(),
163*ec63e07aSXin Li                                   y_array.PtrBoth(), PFFFT_FORWARD));
164*ec63e07aSXin Li         }
165*ec63e07aSXin Li 
166*ec63e07aSXin Li         t1 = UclockSec();
167*ec63e07aSXin Li         SAPI_RETURN_IF_ERROR(api.pffft_destroy_setup(&s_reg));
168*ec63e07aSXin Li 
169*ec63e07aSXin Li         flops = (max_iter * 2) * ((complex ? 5 : 2.5) * static_cast<double>(n) *
170*ec63e07aSXin Li                                   log(static_cast<double>(n)) / M_LN2);
171*ec63e07aSXin Li         ShowOutput("PFFFT", n, complex, flops, t0, t1, max_iter);
172*ec63e07aSXin Li 
173*ec63e07aSXin Li         LOG(INFO) << "n = " << n << " SUCCESSFULLY";
174*ec63e07aSXin Li       }
175*ec63e07aSXin Li     }
176*ec63e07aSXin Li   }
177*ec63e07aSXin Li 
178*ec63e07aSXin Li   return absl::OkStatus();
179*ec63e07aSXin Li }
180*ec63e07aSXin Li 
main(int argc,char * argv[])181*ec63e07aSXin Li int main(int argc, char* argv[]) {
182*ec63e07aSXin Li   absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
183*ec63e07aSXin Li   absl::ParseCommandLine(argc, argv);
184*ec63e07aSXin Li   absl::InitializeLog();
185*ec63e07aSXin Li 
186*ec63e07aSXin Li   if (absl::Status status = PffftMain(); !status.ok()) {
187*ec63e07aSXin Li     LOG(ERROR) << "Initialization failed: " << status.ToString();
188*ec63e07aSXin Li     return EXIT_FAILURE;
189*ec63e07aSXin Li   }
190*ec63e07aSXin Li 
191*ec63e07aSXin Li   return EXIT_SUCCESS;
192*ec63e07aSXin Li }
193