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>
72 lines
3.6 KiB
Python
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)
|