our_knp/cats-dogs/build_tuned_cpu.py
int 8f43927575 Initial import: KNP experiments (examples, viz, cats-dogs, reports)
examples/ is based on KasperskyLab/knp at 55470ed6 with local changes
to the mnist-learn altai/blifat models, cuda-backend CMake and model_loader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:17:15 +03:00

72 lines
3.6 KiB
Python

"""Build a separate configurable CPU backend; original KNP files/libs stay intact."""
from pathlib import Path
import shlex
import subprocess
root = Path('/home/int/run/cats-dogs/acceleration')
root.mkdir(exist_ok=True)
header_original = Path('/mnt/c/KNP/examples/knp/backends/cpu/cpu-multi-threaded-backend/include/knp/backends/cpu-multi-threaded/backend.h')
header = header_original.read_text()
old_types = 'knp::neuron_traits::LIFNeuron>;'
assert header.count(old_types) == 1
header = header.replace(old_types, '''knp::neuron_traits::LIFNeuron,
knp::neuron_traits::AltAILIF, knp::neuron_traits::SynapticResourceSTDPAltAILIFNeuron>;''')
header_path = root / 'include/knp/backends/cpu-multi-threaded/backend.h'
header_path.parent.mkdir(parents=True, exist_ok=True)
header_path.write_text(header)
original = Path('/mnt/c/KNP/examples/knp/backends/cpu/cpu-multi-threaded-backend/impl/backend.cpp')
source = original.read_text()
helper = '''
// Experiment-local factory configuration; the original backend is unchanged.
static size_t configured_size(const char* name, size_t fallback, size_t maximum)
{
const char* value = std::getenv(name);
if (!value || !*value) return fallback;
if (*value < '0' || *value > '9') throw std::invalid_argument(name);
char* end = nullptr;
errno = 0;
const auto parsed = std::strtoull(value, &end, 10);
if (errno || *end || !parsed || parsed > maximum) throw std::invalid_argument(name);
return static_cast<size_t>(parsed);
}
'''
source = source.replace('#include <functional>', '#include <functional>\n#include <cstdlib>\n#include <cerrno>\n#include <stdexcept>')
marker = 'std::shared_ptr<MultiThreadedCPUBackend> MultiThreadedCPUBackend::create()'
assert marker in source
source = source.replace(marker, helper + marker)
old = 'return std::make_shared<MultiThreadedCPUBackend>();'
assert source.count(old) == 1
source = source.replace(old, '''return std::make_shared<MultiThreadedCPUBackend>(
configured_size("KNP_CPU_THREADS", 2, 256),
configured_size("KNP_CPU_POPULATION_PART", 64, 1000000),
configured_size("KNP_CPU_PROJECTION_PART", 8192, 10000000));''')
(root / 'cpu_backend.cpp').write_text(source)
build = Path('/home/int/knp-build/knp/backends/cpu/cpu-multi-threaded-backend')
folder = build / 'CMakeFiles/knp-cpu-multi-threaded-backend.dir'
flags = {}
for line in (folder / 'flags.make').read_text().splitlines():
if ' = ' in line:
key, value = line.split(' = ', 1)
flags[key] = shlex.split(value)
obj = root / 'cpu_backend.o'
subprocess.run(['/usr/bin/c++', *flags['CXX_DEFINES'], '-I' + str(root / 'include'), *flags['CXX_INCLUDES'],
*flags['CXX_FLAGS'], '-c', str(root / 'cpu_backend.cpp'), '-o', str(obj)], check=True)
network_obj = root / 'get_network.o'
subprocess.run(['/usr/bin/c++', *flags['CXX_DEFINES'], '-I' + str(root / 'include'), *flags['CXX_INCLUDES'],
*flags['CXX_FLAGS'], '-c', str(original.with_name('get_network.cpp')), '-o', str(network_obj)], check=True)
link = shlex.split((folder / 'link.txt').read_text())
rebuilt = []
for item in link:
if item.startswith('-Wl,--dependency-file='):
continue
if item.endswith('/impl/backend.cpp.o'):
item = str(obj)
elif item.endswith('/impl/get_network.cpp.o'):
item = str(network_obj)
elif item.startswith('-Wl,-soname,'):
item = '-Wl,-soname,libknp-cpu-tuned-backend.so'
rebuilt.append(item)
rebuilt[rebuilt.index('-o') + 1] = str(root / 'libknp-cpu-tuned-backend.so')
subprocess.run(rebuilt, cwd=build, check=True)
print(root / 'libknp-cpu-tuned-backend.so', flush=True)