mirror of
https://github.com/pybind/pybind11.git
synced 2026-04-19 22:39:09 +00:00
Remove ubench/ directory.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
prune tests
|
||||
prune ubench
|
||||
include README_smart_holder.rst
|
||||
recursive-include pybind11/include/pybind11 *.h
|
||||
recursive-include pybind11 *.py
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include "number_bucket.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
namespace hc { // holder comparison
|
||||
|
||||
using nb_up = pybind11_ubench::number_bucket<1>;
|
||||
using nb_sp = pybind11_ubench::number_bucket<2>;
|
||||
using nb_pu = pybind11_ubench::number_bucket<3>;
|
||||
using nb_sh = pybind11_ubench::number_bucket<4>;
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
template <typename WrappedType, typename HolderType>
|
||||
void wrap_number_bucket(py::module m, const char *class_name) {
|
||||
py::class_<WrappedType, HolderType>(m, class_name)
|
||||
.def(py::init<std::size_t>(), py::arg("data_size") = 0)
|
||||
.def("sum", &WrappedType::sum)
|
||||
.def("add", &WrappedType::add, py::arg("other"));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class padded_unique_ptr {
|
||||
std::unique_ptr<T> ptr;
|
||||
char padding[sizeof(py::smart_holder) - sizeof(std::unique_ptr<T>)];
|
||||
|
||||
public:
|
||||
padded_unique_ptr(T *p) : ptr(p) {}
|
||||
T *get() { return ptr.get(); }
|
||||
};
|
||||
|
||||
static_assert(sizeof(padded_unique_ptr<nb_pu>) == sizeof(py::smart_holder),
|
||||
"Unexpected sizeof mismatch.");
|
||||
|
||||
} // namespace hc
|
||||
|
||||
PYBIND11_DECLARE_HOLDER_TYPE(T, hc::padded_unique_ptr<T>);
|
||||
|
||||
PYBIND11_MODULE(pybind11_ubench_holder_comparison, m) {
|
||||
using namespace hc;
|
||||
wrap_number_bucket<nb_up, std::unique_ptr<nb_up>>(m, "number_bucket_up");
|
||||
wrap_number_bucket<nb_sp, std::shared_ptr<nb_sp>>(m, "number_bucket_sp");
|
||||
m.def("sizeof_smart_holder", []() { return sizeof(py::smart_holder); });
|
||||
wrap_number_bucket<nb_pu, padded_unique_ptr<nb_pu>>(m, "number_bucket_pu");
|
||||
wrap_number_bucket<nb_sh, py::smart_holder>(m, "number_bucket_sh");
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
"""Simple comparison of holder performances, relative to unique_ptr holder."""
|
||||
|
||||
# ruff: noqa
|
||||
# This code has no unit tests.
|
||||
# ruff cleanup deferred until the next time this code is actually used.
|
||||
|
||||
import collections
|
||||
import sys
|
||||
import time
|
||||
from typing import Any, Callable, Dict, List
|
||||
|
||||
import pybind11_ubench_holder_comparison as m # type: ignore[import-not-found]
|
||||
|
||||
number_bucket_pc = None
|
||||
|
||||
|
||||
def pflush(*args: Any, **kwargs: Any) -> None:
|
||||
print(*args, **kwargs)
|
||||
# Using "file" here because it is the name of the built-in keyword argument.
|
||||
file = kwargs.get("file", sys.stdout) # pylint: disable=redefined-builtin
|
||||
file.flush() # file object must have a flush method.
|
||||
|
||||
|
||||
def run(args: List[str]) -> None:
|
||||
if not args:
|
||||
size_exponent_min = 0
|
||||
size_exponent_max = 16
|
||||
size_exponent_step = 4
|
||||
call_repetitions_first_pass = 100
|
||||
call_repetitions_target_elapsed_secs = 0.1
|
||||
num_samples = 10
|
||||
selected_holder_type = "all"
|
||||
else:
|
||||
assert len(args) == 7, (
|
||||
"size_exponent_min size_exponent_max size_exponent_step"
|
||||
" call_repetitions_first_pass call_repetitions_target_elapsed_secs"
|
||||
" num_samples selected_holder_type"
|
||||
)
|
||||
size_exponent_min = int(args[0])
|
||||
size_exponent_max = int(args[1])
|
||||
size_exponent_step = int(args[2])
|
||||
call_repetitions_first_pass = int(args[3])
|
||||
call_repetitions_target_elapsed_secs = float(args[4])
|
||||
num_samples = int(args[5])
|
||||
selected_holder_type = args[6]
|
||||
pflush(
|
||||
"command-line arguments:",
|
||||
size_exponent_min,
|
||||
size_exponent_max,
|
||||
size_exponent_step,
|
||||
call_repetitions_first_pass,
|
||||
"%.3f" % call_repetitions_target_elapsed_secs,
|
||||
num_samples,
|
||||
selected_holder_type,
|
||||
)
|
||||
pflush("sizeof_smart_holder:", m.sizeof_smart_holder())
|
||||
|
||||
def find_call_repetitions(
|
||||
callable: Callable[[int], float],
|
||||
time_delta_floor: float = 1.0e-6,
|
||||
target_elapsed_secs_multiplier: float = 1.05, # Empirical.
|
||||
target_elapsed_secs_tolerance: float = 0.05,
|
||||
max_iterations: int = 100,
|
||||
) -> int:
|
||||
td_target = (
|
||||
call_repetitions_target_elapsed_secs * target_elapsed_secs_multiplier
|
||||
)
|
||||
crd = call_repetitions_first_pass
|
||||
for _ in range(max_iterations):
|
||||
td = callable(crd)
|
||||
crd = max(1, int(td_target * crd / max(td, time_delta_floor)))
|
||||
if abs(td - td_target) / td_target < target_elapsed_secs_tolerance:
|
||||
return crd
|
||||
raise RuntimeError("find_call_repetitions failure: max_iterations exceeded.")
|
||||
|
||||
for size_exponent in range(
|
||||
size_exponent_min, size_exponent_max + 1, size_exponent_step
|
||||
):
|
||||
data_size = 2**size_exponent
|
||||
pflush(data_size, "data_size")
|
||||
ratios: Dict[str, List[float]] = collections.defaultdict(list)
|
||||
call_repetitions = None
|
||||
for _ in range(num_samples):
|
||||
row_0 = None
|
||||
for nb_label, nb_type in [
|
||||
("up", m.number_bucket_up),
|
||||
("sp", m.number_bucket_sp),
|
||||
("pu", m.number_bucket_pu),
|
||||
("sh", m.number_bucket_sh),
|
||||
("pc", number_bucket_pc),
|
||||
]:
|
||||
if nb_label == "pc" and nb_type is None:
|
||||
continue
|
||||
if selected_holder_type != "all" and nb_label != selected_holder_type:
|
||||
continue
|
||||
nb1 = nb_type(data_size)
|
||||
nb2 = nb_type(data_size)
|
||||
|
||||
def many_sum(call_repetitions: int) -> float:
|
||||
assert int(round(nb1.sum())) == data_size
|
||||
t0 = time.time()
|
||||
for _ in range(call_repetitions):
|
||||
nb1.sum()
|
||||
return time.time() - t0
|
||||
|
||||
def many_add(call_repetitions: int) -> float:
|
||||
assert nb1.add(nb2) == data_size
|
||||
t0 = time.time()
|
||||
for _ in range(call_repetitions):
|
||||
nb1.add(nb2)
|
||||
return time.time() - t0
|
||||
|
||||
if call_repetitions is None:
|
||||
call_repetitions = find_call_repetitions(many_sum)
|
||||
pflush(call_repetitions, "call_repetitions")
|
||||
|
||||
td_sum = many_sum(call_repetitions)
|
||||
td_add = many_add(call_repetitions)
|
||||
row = [td_sum, td_add]
|
||||
if row_0 is None:
|
||||
pflush(" Sum Add ratS ratA")
|
||||
row_0 = row
|
||||
else:
|
||||
for curr, prev in zip(row, row_0): # type: ignore[unreachable]
|
||||
if prev:
|
||||
rat = curr / prev
|
||||
else:
|
||||
rat = -1
|
||||
row.append(curr / prev)
|
||||
ratios[nb_label + "_ratS"].append(row[-2])
|
||||
ratios[nb_label + "_ratA"].append(row[-1])
|
||||
pflush(nb_label, " ".join(["%.3f" % v for v in row]))
|
||||
pflush(" Min Mean Max")
|
||||
for key, rat in ratios.items():
|
||||
print(
|
||||
key,
|
||||
"{:5.3f} {:5.3f} {:5.3f}".format(
|
||||
min(rat), sum(rat) / len(rat), max(rat)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run(args=sys.argv[1:])
|
||||
@@ -1,71 +0,0 @@
|
||||
"""Extract mean ratios from holder_comparison.py output."""
|
||||
|
||||
# ruff: noqa
|
||||
# This code has no unit tests.
|
||||
# ruff cleanup deferred until the next time this code is actually used.
|
||||
|
||||
import sys
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
def run(args: List[str]) -> None:
|
||||
assert len(args) == 1, "log_holder_comparison.txt"
|
||||
|
||||
log_lines = open(args[0]).read().splitlines()
|
||||
|
||||
for ratx in ("_ratS ", "_ratA "):
|
||||
print(ratx)
|
||||
header = None
|
||||
header_row = None
|
||||
data_row = None
|
||||
data_row_buffer: List[List[str]] = []
|
||||
|
||||
def show() -> Optional[List[str]]:
|
||||
if header_row:
|
||||
if header is None: # type: ignore[unreachable]
|
||||
print(",".join(header_row))
|
||||
else:
|
||||
assert header == header_row
|
||||
if data_row is not None:
|
||||
print(",".join(data_row)) # type: ignore[unreachable]
|
||||
data_row_buffer.append(data_row)
|
||||
return header_row
|
||||
|
||||
for line in log_lines:
|
||||
if line.endswith(" data_size"):
|
||||
header = show()
|
||||
flds = line.split()
|
||||
assert len(flds) == 2
|
||||
header_row = ["data_size"]
|
||||
data_row = [flds[0]]
|
||||
elif line.endswith(" call_repetitions"):
|
||||
flds = line.split()
|
||||
assert len(flds) == 2
|
||||
assert header_row is not None
|
||||
assert data_row is not None
|
||||
header_row.append("calls")
|
||||
data_row.append(flds[0])
|
||||
header_row.append("up")
|
||||
data_row.append("1.000")
|
||||
elif line[2:].startswith(ratx):
|
||||
flds = line.split()
|
||||
assert len(flds) == 4
|
||||
assert header_row is not None
|
||||
assert data_row is not None
|
||||
header_row.append(line[:2])
|
||||
data_row.append(flds[2])
|
||||
show()
|
||||
|
||||
assert header_row is not None
|
||||
print("Scaled to last column:")
|
||||
print(",".join(header_row))
|
||||
for data_row in data_row_buffer:
|
||||
data_row_rescaled = data_row[:2]
|
||||
unit = float(data_row[-1])
|
||||
for fld in data_row[2:]:
|
||||
data_row_rescaled.append("%.3f" % (float(fld) / unit))
|
||||
print(",".join(data_row_rescaled))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run(args=sys.argv[1:])
|
||||
@@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace pybind11_ubench {
|
||||
|
||||
template <int Serial>
|
||||
struct number_bucket {
|
||||
std::vector<double> data;
|
||||
|
||||
explicit number_bucket(std::size_t data_size = 0) : data(data_size, 1.0) {}
|
||||
|
||||
double sum() const {
|
||||
std::size_t n = 0;
|
||||
double s = 0;
|
||||
const double *a = &*data.begin();
|
||||
const double *e = &*data.end();
|
||||
while (a != e) {
|
||||
s += *a++;
|
||||
n++;
|
||||
}
|
||||
if (n != data.size()) {
|
||||
std::cerr << "Internal consistency failure (sum)." << std::endl;
|
||||
std::terminate();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
std::size_t add(const number_bucket &other) {
|
||||
if (other.data.size() != data.size()) {
|
||||
std::cerr << "Incompatible data sizes (add)." << std::endl;
|
||||
std::terminate();
|
||||
}
|
||||
std::size_t n = 0;
|
||||
double *a = &*data.begin();
|
||||
const double *e = &*data.end();
|
||||
const double *b = &*other.data.begin();
|
||||
while (a != e) {
|
||||
*a++ += *b++;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
private:
|
||||
number_bucket(const number_bucket &) = delete;
|
||||
number_bucket(number_bucket &&) = delete;
|
||||
number_bucket &operator=(const number_bucket &) = delete;
|
||||
number_bucket &operator=(number_bucket &&) = delete;
|
||||
};
|
||||
|
||||
} // namespace pybind11_ubench
|
||||
@@ -1,6 +0,0 @@
|
||||
from "pybind11/ubench/number_bucket.h":
|
||||
namespace `pybind11_ubench`:
|
||||
class `number_bucket<0>` as number_bucket_pc:
|
||||
def __init__(self, data_size: int = default)
|
||||
def sum(self) -> float
|
||||
def add(self, other: number_bucket_pc) -> int
|
||||
Reference in New Issue
Block a user