Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,19 @@ include(GNUInstallDirs)
set(VISP_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Location of header files")
set(VISP_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Location of library files")
set(VISP_BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Location of binary files")
set(VISP_SHARE_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/visioncpp" CACHE PATH "Location of SDK data (generic runner source)")
if(VISP_INSTALL_MODELS)
set(VISP_MODEL_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/visioncpp" CACHE PATH "Directory to install default models to")
endif()

# The installed libvisioncpp.so records libggml.so.0 in DT_NEEDED. Without a RUNPATH a
# consumer links successfully and then fails at startup with
# "libggml.so.0: cannot open shared object file" -- the linker resolves the path CMake gives
# it, and the loader searches again at run time with nothing to go on.
# $ORIGIN is the directory holding the .so itself; ggml installs into the same lib/, so this
# one line removes the need for LD_LIBRARY_PATH.
set(CMAKE_INSTALL_RPATH "$ORIGIN")

if(PROJECT_IS_TOP_LEVEL)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
Expand Down Expand Up @@ -169,6 +178,13 @@ install(TARGETS visioncpp
LIBRARY DESTINATION ${VISP_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${VISP_LIB_INSTALL_DIR})
install(DIRECTORY include/ DESTINATION ${VISP_INCLUDE_INSTALL_DIR})
# Internal headers that generated code includes; consumers of the install tree need them.
install(FILES src/visp/nn.h DESTINATION ${VISP_INCLUDE_INSTALL_DIR}/visp)
install(DIRECTORY src/util/ DESTINATION ${VISP_INCLUDE_INSTALL_DIR}/util
FILES_MATCHING PATTERN "*.h")

# Generic runner source. Consumers compile it together with their generated <Arch>.cpp.
install(FILES tools/verify/backbone/run_dump.cpp DESTINATION ${VISP_SHARE_INSTALL_DIR})
if(PROJECT_IS_TOP_LEVEL)
install(FILES README.md LICENSE DESTINATION .)
endif()
Expand All @@ -190,7 +206,7 @@ configure_package_config_file(
scripts/cmake/visioncpp-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/visioncpp-config.cmake
INSTALL_DESTINATION ${VISP_LIB_INSTALL_DIR}/cmake/visioncpp
PATH_VARS VISP_INCLUDE_INSTALL_DIR VISP_LIB_INSTALL_DIR VISP_BIN_INSTALL_DIR
PATH_VARS VISP_INCLUDE_INSTALL_DIR VISP_LIB_INSTALL_DIR VISP_BIN_INSTALL_DIR VISP_SHARE_INSTALL_DIR
)
write_basic_package_version_file(
visioncpp-version.cmake
Expand Down
5 changes: 5 additions & 0 deletions scripts/cmake/visioncpp-config.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

set_and_check(VISP_INCLUDE_DIR "@PACKAGE_VISP_INCLUDE_INSTALL_DIR@")
set_and_check(VISP_LIB_DIR "@PACKAGE_VISP_LIB_INSTALL_DIR@")
set_and_check(VISP_SHARE_DIR "@PACKAGE_VISP_SHARE_INSTALL_DIR@")

# Generic runner source for generated models. For example:
# add_executable(run ${VISP_RUNNER} ${GEN}/${ARCH}.cpp)
set(VISP_RUNNER "${VISP_SHARE_DIR}/run_dump.cpp")

include(CMakeFindDependencyMacro)
find_dependency(ggml)
Expand Down
34 changes: 33 additions & 1 deletion tools/verify/backbone/run_dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ int main(int argc, char** argv) {
std::string pref = argv[3];
const int SZ = argc > 4 ? atoi(argv[4]) : 512;

backend_device backend = backend_init();
// backend_init() picks the best device it can find. When a build includes an
// accelerator backend that is not actually present, that choice fails late and
// unhelpfully, and numeric comparison wants the CPU anyway.
const char* backend_env = std::getenv("VISP_BACKEND");
backend_device backend = (backend_env && std::string(backend_env) == "cpu")
? backend_init(backend_type::cpu)
: backend_init();
model_file file = model_load(gguf);
model_weights weights = model_init(file.n_tensors());
model_transfer(file, weights, backend, backend.preferred_float_type(), file.tensor_layout());
Expand All @@ -50,6 +56,15 @@ int main(int argc, char** argv) {
tensor last = FWD(m, input, p); // 내부에서 compute_graph_output 이 out_i 를 그래프에 등록
ggml_build_forward_expand(graph, last);

// VISP_DUMP_NODES=<dir> writes every named intermediate as <name>.bin. Comparing only
// the final output says that something diverged, not where.
const char* dump_dir = std::getenv("VISP_DUMP_NODES");
if (dump_dir) {
for (int i = 0; i < ggml_graph_n_nodes(graph.graph); ++i) {
ggml_set_output(ggml_graph_node(graph.graph, i));
}
}

compute_graph_allocate(graph, backend);
auto in = load_bin(inb, (size_t)3 * SZ * SZ);
transfer_to_backend(input, std::span<const float>(in.data(), in.size()));
Expand All @@ -71,5 +86,22 @@ int main(int argc, char** argv) {
(long long)t->ne[0], (long long)t->ne[1], (long long)t->ne[2], (long long)t->ne[3]);
}
printf("dumped %d outputs → %s.out.*.bin\n", n, pref.c_str());

if (dump_dir) {
int written = 0;
for (int i = 0; i < ggml_graph_n_nodes(graph.graph); ++i) {
tensor t = ggml_graph_node(graph.graph, i);
const char* nm = ggml_get_name(t);
if (!nm || !nm[0] || t->type != GGML_TYPE_F32) {
continue;
}
std::vector<float> d(ggml_nelements(t));
transfer_from_backend(t, std::span<float>(d.data(), d.size()));
std::ofstream of(std::string(dump_dir) + "/" + nm + ".bin", std::ios::binary);
of.write(reinterpret_cast<char const*>(d.data()), d.size() * sizeof(float));
++written;
}
printf("- VISP_DUMP_NODES: %d intermediates → %s\n", written, dump_dir);
}
return 0;
}
Loading