2020-08-26 22:18:31 +08:00
|
|
|
// Copyright 2020 Google LLC
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2020-08-20 19:19:49 +08:00
|
|
|
#include <glog/logging.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/times.h>
|
|
|
|
#include <syscall.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2020-08-26 19:23:33 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <cmath>
|
|
|
|
#include <cstdio>
|
|
|
|
|
2020-08-20 19:19:49 +08:00
|
|
|
#include "pffft_sapi.sapi.h"
|
|
|
|
#include "sandboxed_api/util/flag.h"
|
|
|
|
#include "sandboxed_api/vars.h"
|
|
|
|
|
|
|
|
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all);
|
|
|
|
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all_and_log);
|
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
class PffftSapiSandbox : public pffftSandbox {
|
2020-08-20 19:19:49 +08:00
|
|
|
public:
|
|
|
|
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
|
|
|
sandbox2::PolicyBuilder*) override {
|
|
|
|
return sandbox2::PolicyBuilder()
|
|
|
|
.AllowStaticStartup()
|
|
|
|
.AllowOpen()
|
|
|
|
.AllowRead()
|
|
|
|
.AllowWrite()
|
|
|
|
.AllowSystemMalloc()
|
|
|
|
.AllowExit()
|
|
|
|
.AllowSyscalls({
|
|
|
|
__NR_futex,
|
|
|
|
__NR_close,
|
|
|
|
__NR_getrusage,
|
|
|
|
})
|
|
|
|
.BuildOrDie();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-08-26 19:23:33 +08:00
|
|
|
double UclockSec(void) { return (double)clock() / (double)CLOCKS_PER_SEC; }
|
2020-08-20 19:19:49 +08:00
|
|
|
|
|
|
|
int array_output_format = 0;
|
|
|
|
|
2020-08-26 19:23:33 +08:00
|
|
|
void ShowOutput(const char* name, int N, int cplx, float flops, float t0,
|
|
|
|
float t1, int max_iter) {
|
2020-08-20 19:19:49 +08:00
|
|
|
float mflops = flops / 1e6 / (t1 - t0 + 1e-16);
|
|
|
|
if (array_output_format) {
|
|
|
|
if (flops != -1) {
|
|
|
|
printf("|%9.0f ", mflops);
|
|
|
|
} else
|
|
|
|
printf("| n/a ");
|
|
|
|
} else {
|
|
|
|
if (flops != -1) {
|
|
|
|
printf("N=%5d, %s %16s : %6.0f MFlops [t=%6.0f ns, %d runs]\n", N,
|
|
|
|
(cplx ? "CPLX" : "REAL"), name, mflops,
|
|
|
|
(t1 - t0) / 2 / max_iter * 1e9, max_iter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
2020-08-26 22:18:31 +08:00
|
|
|
|
|
|
|
// Initialize Google's logging library.
|
2020-08-20 19:19:49 +08:00
|
|
|
google::InitGoogleLogging(argv[0]);
|
|
|
|
|
|
|
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
2020-08-26 22:18:31 +08:00
|
|
|
|
|
|
|
// Nvalues is a vector keeping the values by which iterates N, its value
|
|
|
|
// representing the input length. More concrete, N is the number of
|
|
|
|
// data points the caclulus is up to (determinating its accuracy).
|
|
|
|
// To show the performance of Fast-Fourier Transformations the program is
|
|
|
|
// testing for various values of N.
|
2020-08-20 19:19:49 +08:00
|
|
|
int Nvalues[] = {64, 96, 128, 160, 192, 256,
|
|
|
|
384, 5 * 96, 512, 5 * 128, 3 * 256, 800,
|
|
|
|
1024, 2048, 2400, 4096, 8192, 9 * 1024,
|
2020-08-26 22:18:31 +08:00
|
|
|
16384, 32768};
|
2020-08-20 19:19:49 +08:00
|
|
|
int i;
|
|
|
|
|
2020-08-20 20:37:34 +08:00
|
|
|
LOG(INFO) << "Initializing sandbox...\n";
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
PffftSapiSandbox sandbox;
|
2020-08-26 19:23:33 +08:00
|
|
|
absl::Status init_status = sandbox.Init();
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-26 19:23:33 +08:00
|
|
|
LOG(INFO) << "Initialization: " << init_status.ToString().c_str() << "\n";
|
2020-08-20 19:19:49 +08:00
|
|
|
|
|
|
|
pffftApi api(&sandbox);
|
2020-08-26 19:23:33 +08:00
|
|
|
int cplx = 0;
|
2020-08-20 19:19:49 +08:00
|
|
|
|
|
|
|
do {
|
2020-08-26 19:23:33 +08:00
|
|
|
for (int N : Nvalues) {
|
|
|
|
const int Nfloat = N * (cplx ? 2 : 1);
|
2020-08-20 19:19:49 +08:00
|
|
|
int Nbytes = Nfloat * sizeof(float);
|
|
|
|
|
2020-08-26 19:23:33 +08:00
|
|
|
float wrk[2 * Nfloat + 15 * sizeof(float)];
|
|
|
|
sapi::v::Array<float> wrk_(wrk, 2 * Nfloat + 15 * sizeof(float));
|
2020-08-20 19:19:49 +08:00
|
|
|
|
|
|
|
float X[Nbytes], Y[Nbytes], Z[Nbytes];
|
|
|
|
sapi::v::Array<float> X_(X, Nbytes), Y_(Y, Nbytes), Z_(Z, Nbytes);
|
|
|
|
|
|
|
|
double t0, t1, flops;
|
|
|
|
|
|
|
|
int max_iter = 5120000 / N * 4;
|
|
|
|
#ifdef __arm__
|
|
|
|
max_iter /= 4;
|
|
|
|
#endif
|
2020-08-26 19:23:33 +08:00
|
|
|
int iter, k;
|
2020-08-20 19:19:49 +08:00
|
|
|
|
|
|
|
for (k = 0; k < Nfloat; ++k) {
|
|
|
|
X[k] = 0;
|
|
|
|
}
|
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
// FFTPack benchmark
|
2020-08-20 19:19:49 +08:00
|
|
|
{
|
2020-08-26 22:18:31 +08:00
|
|
|
// SIMD_SZ == 4 (returning value of pffft_simd_size())
|
2020-08-20 19:19:49 +08:00
|
|
|
int max_iter_ = max_iter / 4;
|
|
|
|
|
|
|
|
if (max_iter_ == 0) max_iter_ = 1;
|
|
|
|
if (cplx) {
|
|
|
|
api.cffti(N, wrk_.PtrBoth()).IgnoreError();
|
|
|
|
} else {
|
|
|
|
api.rffti(N, wrk_.PtrBoth()).IgnoreError();
|
|
|
|
}
|
2020-08-26 19:23:33 +08:00
|
|
|
t0 = UclockSec();
|
2020-08-20 19:19:49 +08:00
|
|
|
|
|
|
|
for (iter = 0; iter < max_iter_; ++iter) {
|
|
|
|
if (cplx) {
|
|
|
|
api.cfftf(N, X_.PtrBoth(), wrk_.PtrBoth()).IgnoreError();
|
|
|
|
api.cfftb(N, X_.PtrBoth(), wrk_.PtrBoth()).IgnoreError();
|
|
|
|
} else {
|
|
|
|
api.rfftf(N, X_.PtrBoth(), wrk_.PtrBoth()).IgnoreError();
|
|
|
|
api.rfftb(N, X_.PtrBoth(), wrk_.PtrBoth()).IgnoreError();
|
|
|
|
}
|
|
|
|
}
|
2020-08-26 19:23:33 +08:00
|
|
|
t1 = UclockSec();
|
2020-08-20 19:19:49 +08:00
|
|
|
|
|
|
|
flops =
|
|
|
|
(max_iter_ * 2) * ((cplx ? 5 : 2.5) * N * log((double)N) / M_LN2);
|
2020-08-26 19:23:33 +08:00
|
|
|
ShowOutput("FFTPack", N, cplx, flops, t0, t1, max_iter_);
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
2020-08-26 22:18:31 +08:00
|
|
|
|
|
|
|
// PFFFT benchmark
|
2020-08-20 19:19:49 +08:00
|
|
|
{
|
|
|
|
sapi::StatusOr<PFFFT_Setup*> s =
|
|
|
|
api.pffft_new_setup(N, cplx ? PFFFT_COMPLEX : PFFFT_REAL);
|
|
|
|
|
2020-08-26 19:23:33 +08:00
|
|
|
LOG(INFO) << "Setup status is: " << s.status().ToString().c_str()
|
|
|
|
<< "\n";
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
if (!s.ok()) {
|
|
|
|
printf("Sandbox failed.\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
sapi::v::RemotePtr s_reg(s.value());
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
t0 = UclockSec();
|
|
|
|
for (iter = 0; iter < max_iter; ++iter) {
|
|
|
|
api.pffft_transform(&s_reg, X_.PtrBoth(), Z_.PtrBoth(),
|
|
|
|
Y_.PtrBoth(), PFFFT_FORWARD)
|
|
|
|
.IgnoreError();
|
|
|
|
api.pffft_transform(&s_reg, X_.PtrBoth(), Z_.PtrBoth(),
|
|
|
|
Y_.PtrBoth(), PFFFT_FORWARD)
|
|
|
|
.IgnoreError();
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
t1 = UclockSec();
|
|
|
|
api.pffft_destroy_setup(&s_reg).IgnoreError();
|
|
|
|
|
|
|
|
flops =
|
|
|
|
(max_iter * 2) * ((cplx ? 5 : 2.5) * N * log((double)N) / M_LN2);
|
|
|
|
ShowOutput("PFFFT", N, cplx, flops, t0, t1, max_iter);
|
|
|
|
|
2020-08-20 20:37:34 +08:00
|
|
|
LOG(INFO) << "N = " << N << " SUCCESSFULLY\n\n";
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cplx = !cplx;
|
|
|
|
} while (cplx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|