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
|
|
|
|
//
|
2022-01-28 17:38:27 +08:00
|
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
2020-08-26 22:18:31 +08:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2022-02-09 21:19:56 +08:00
|
|
|
#include <syscall.h>
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-26 19:23:33 +08:00
|
|
|
#include <cmath>
|
|
|
|
#include <cstdio>
|
2020-08-28 00:46:59 +08:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <ctime>
|
2020-08-26 19:23:33 +08:00
|
|
|
|
2020-09-15 22:46:03 +08:00
|
|
|
#include <glog/logging.h>
|
2022-02-09 21:19:56 +08:00
|
|
|
#include "gflags/gflags.h"
|
2020-09-15 22:46:03 +08:00
|
|
|
#include "pffft_sapi.sapi.h" // NOLINT(build/include)
|
2020-08-20 19:19:49 +08:00
|
|
|
#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-27 20:54:57 +08:00
|
|
|
class PffftSapiSandbox : public PffftSandbox {
|
2020-08-20 19:19:49 +08:00
|
|
|
public:
|
2020-08-28 00:46:59 +08:00
|
|
|
std::unique_ptr<sandbox2::Policy> ModifyPolicy(sandbox2::PolicyBuilder*) {
|
2020-08-20 19:19:49 +08:00
|
|
|
return sandbox2::PolicyBuilder()
|
|
|
|
.AllowStaticStartup()
|
|
|
|
.AllowOpen()
|
|
|
|
.AllowRead()
|
|
|
|
.AllowWrite()
|
|
|
|
.AllowSystemMalloc()
|
|
|
|
.AllowExit()
|
|
|
|
.AllowSyscalls({
|
|
|
|
__NR_futex,
|
|
|
|
__NR_close,
|
|
|
|
__NR_getrusage,
|
|
|
|
})
|
|
|
|
.BuildOrDie();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
// output_format flag determines whether the output shows information in detail
|
|
|
|
// or not. By default, the flag is set as 0, meaning an elaborate display
|
|
|
|
// (see ShowOutput method).
|
|
|
|
static bool ValidateFlag(const char* flagname, int32_t value) {
|
|
|
|
if (value >= 0 && value < 32768) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG(ERROR) << "Invalid value for --" << flagname << ".";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFINE_int32(output_format, 0, "Value to specific the output format.");
|
|
|
|
DEFINE_validator(output_format, &ValidateFlag);
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
double UclockSec() { return static_cast<double>(clock()) / CLOCKS_PER_SEC; }
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:55:55 +08:00
|
|
|
void ShowOutput(const char* name, int n, int complex, float flops, float t0,
|
2020-08-26 19:23:33 +08:00
|
|
|
float t1, int max_iter) {
|
2020-08-20 19:19:49 +08:00
|
|
|
float mflops = flops / 1e6 / (t1 - t0 + 1e-16);
|
2020-08-28 00:46:59 +08:00
|
|
|
if (FLAGS_output_format) {
|
2020-08-20 19:19:49 +08:00
|
|
|
if (flops != -1) {
|
|
|
|
printf("|%9.0f ", mflops);
|
2020-09-15 22:46:03 +08:00
|
|
|
} else {
|
2020-08-20 19:19:49 +08:00
|
|
|
printf("| n/a ");
|
|
|
|
}
|
2020-09-15 22:46:03 +08:00
|
|
|
} else if (flops != -1) {
|
|
|
|
printf("n=%5d, %s %16s : %6.0f MFlops [t=%6.0f ns, %d runs]\n", n,
|
|
|
|
(complex ? "CPLX" : "REAL"), name, mflops,
|
|
|
|
(t1 - t0) / 2 / max_iter * 1e9, max_iter);
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2020-08-27 20:54:57 +08:00
|
|
|
absl::Status PffftMain() {
|
2020-08-31 19:17:15 +08:00
|
|
|
LOG(INFO) << "Initializing sandbox...\n";
|
|
|
|
|
2020-08-27 20:54:57 +08:00
|
|
|
PffftSapiSandbox sandbox;
|
|
|
|
SAPI_RETURN_IF_ERROR(sandbox.Init());
|
|
|
|
|
|
|
|
PffftApi api(&sandbox);
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
// kTransformSizes 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.
|
|
|
|
constexpr int kTransformSizes[] = {
|
|
|
|
64, 96, 128, 160, 192, 256, 384, 5 * 96, 512, 5 * 128,
|
|
|
|
3 * 256, 800, 1024, 2048, 2400, 4096, 8192, 9 * 1024, 16384, 32768};
|
|
|
|
|
2020-08-28 00:55:55 +08:00
|
|
|
for (int complex : {0, 1}) {
|
2020-08-27 20:54:57 +08:00
|
|
|
for (int n : kTransformSizes) {
|
2020-08-28 00:55:55 +08:00
|
|
|
const int n_float = n * (complex ? 2 : 1);
|
2020-08-27 20:54:57 +08:00
|
|
|
int n_bytes = n_float * sizeof(float);
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-27 20:54:57 +08:00
|
|
|
std::vector<float> work(2 * n_float + 15, 0.0);
|
|
|
|
sapi::v::Array<float> work_array(&work[0], work.size());
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
std::vector<float> x(n_bytes, 0.0);
|
|
|
|
sapi::v::Array<float> x_array(&x[0], x.size());
|
|
|
|
|
|
|
|
std::vector<float> y(n_bytes, 0.0);
|
|
|
|
sapi::v::Array<float> y_array(&y[0], y.size());
|
|
|
|
|
|
|
|
std::vector<float> z(n_bytes, 0.0);
|
|
|
|
sapi::v::Array<float> z_array(&z[0], z.size());
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-27 20:54:57 +08:00
|
|
|
double t0;
|
|
|
|
double t1;
|
|
|
|
double flops;
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-27 20:54:57 +08:00
|
|
|
int max_iter = 5120000 / n * 4;
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
for (int k = 0; k < n_float; ++k) {
|
2020-08-27 20:54:57 +08:00
|
|
|
x[k] = 0;
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
|
|
|
|
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-28 00:46:59 +08:00
|
|
|
int simd_size_iter = max_iter / 4;
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
if (simd_size_iter == 0) simd_size_iter = 1;
|
2020-08-28 00:55:55 +08:00
|
|
|
if (complex) {
|
2020-09-03 22:59:54 +08:00
|
|
|
SAPI_RETURN_IF_ERROR(api.cffti(n, work_array.PtrBoth()))
|
2020-08-20 19:19:49 +08:00
|
|
|
} else {
|
2020-09-03 22:59:54 +08:00
|
|
|
SAPI_RETURN_IF_ERROR(api.rffti(n, work_array.PtrBoth()));
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
2020-08-26 19:23:33 +08:00
|
|
|
t0 = UclockSec();
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
for (int iter = 0; iter < simd_size_iter; ++iter) {
|
2020-08-28 00:55:55 +08:00
|
|
|
if (complex) {
|
2020-09-03 22:59:54 +08:00
|
|
|
SAPI_RETURN_IF_ERROR(
|
|
|
|
api.cfftf(n, x_array.PtrBoth(), work_array.PtrBoth()));
|
|
|
|
SAPI_RETURN_IF_ERROR(
|
|
|
|
api.cfftb(n, x_array.PtrBoth(), work_array.PtrBoth()));
|
2020-08-20 19:19:49 +08:00
|
|
|
} else {
|
2020-09-03 22:59:54 +08:00
|
|
|
SAPI_RETURN_IF_ERROR(
|
|
|
|
api.rfftf(n, x_array.PtrBoth(), work_array.PtrBoth()));
|
|
|
|
SAPI_RETURN_IF_ERROR(
|
|
|
|
api.rfftb(n, x_array.PtrBoth(), work_array.PtrBoth()));
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
|
|
|
}
|
2020-08-26 19:23:33 +08:00
|
|
|
t1 = UclockSec();
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
flops = (simd_size_iter * 2) *
|
2020-09-15 22:46:03 +08:00
|
|
|
((complex ? 5 : 2.5) * static_cast<double>(n) *
|
|
|
|
log(static_cast<double>(n)) / M_LN2);
|
2020-08-28 00:55:55 +08:00
|
|
|
ShowOutput("FFTPack", n, complex, flops, t0, t1, simd_size_iter);
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
2020-08-28 00:46:59 +08:00
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
// PFFFT benchmark
|
2020-08-20 19:19:49 +08:00
|
|
|
{
|
2020-08-31 19:48:19 +08:00
|
|
|
SAPI_ASSIGN_OR_RETURN(
|
2020-09-03 22:59:54 +08:00
|
|
|
PFFFT_Setup * s,
|
2020-08-31 19:48:19 +08:00
|
|
|
api.pffft_new_setup(n, complex ? PFFFT_COMPLEX : PFFFT_REAL));
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-31 19:48:19 +08:00
|
|
|
sapi::v::RemotePtr s_reg(s);
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
t0 = UclockSec();
|
2020-08-27 20:54:57 +08:00
|
|
|
for (int iter = 0; iter < max_iter; ++iter) {
|
2020-09-03 22:59:54 +08:00
|
|
|
SAPI_RETURN_IF_ERROR(
|
|
|
|
api.pffft_transform(&s_reg, x_array.PtrBoth(), z_array.PtrBoth(),
|
|
|
|
y_array.PtrBoth(), PFFFT_FORWARD));
|
|
|
|
SAPI_RETURN_IF_ERROR(
|
|
|
|
api.pffft_transform(&s_reg, x_array.PtrBoth(), z_array.PtrBoth(),
|
|
|
|
y_array.PtrBoth(), PFFFT_FORWARD));
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
|
|
|
|
2020-08-26 22:18:31 +08:00
|
|
|
t1 = UclockSec();
|
2020-09-03 22:59:54 +08:00
|
|
|
SAPI_RETURN_IF_ERROR(api.pffft_destroy_setup(&s_reg));
|
2020-08-26 22:18:31 +08:00
|
|
|
|
2020-08-28 00:55:55 +08:00
|
|
|
flops = (max_iter * 2) * ((complex ? 5 : 2.5) * static_cast<double>(n) *
|
2020-09-03 22:59:54 +08:00
|
|
|
log(static_cast<double>(n)) / M_LN2);
|
2020-08-28 00:55:55 +08:00
|
|
|
ShowOutput("PFFFT", n, complex, flops, t0, t1, max_iter);
|
2020-08-26 22:18:31 +08:00
|
|
|
|
2020-08-27 20:54:57 +08:00
|
|
|
LOG(INFO) << "n = " << n << " SUCCESSFULLY";
|
2020-08-20 19:19:49 +08:00
|
|
|
}
|
|
|
|
}
|
2020-08-31 19:48:19 +08:00
|
|
|
}
|
2020-08-20 19:19:49 +08:00
|
|
|
|
2020-08-28 00:46:59 +08:00
|
|
|
return absl::OkStatus();
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
// Initialize Google's logging library.
|
|
|
|
google::InitGoogleLogging(argv[0]);
|
|
|
|
|
|
|
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
|
|
|
|
|
|
|
if (absl::Status status = PffftMain(); !status.ok()) {
|
|
|
|
LOG(ERROR) << "Initialization failed: " << status.ToString();
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2020-08-27 20:54:57 +08:00
|
|
|
return EXIT_SUCCESS;
|
2020-09-15 22:46:03 +08:00
|
|
|
}
|