Skip to content
This repository was archived by the owner on Jul 1, 2025. It is now read-only.

Commit 2b203ab

Browse files
mciprian13facebook-github-bot
authored andcommitted
Add mechanism to archive additional objects to bundle (#5275)
Summary: **Summary** Added mechanism to archive additional objects to bundle: - Added a CMake utility function to serialize files and add to Glow binary files - Enabled this mechanism for the CPUBackend as an example for other backends to use this mechanism (either public or private backends). - All the `.o` objects located in `glow/lib/Backends/CPU/libobj_cpu` will be automatically serialized and added in a variable called `cpuObjectRegistry` with memory buffers as `llvm::MemoryBufferRef` at glow build-time - The command line option `-bundle-objects` controls which of the serialized objects will be archived together with the bundle - The objects can also be chosen dynamically at runtime by using the function: `void LLVMIRGen::addBundleObject()` **Documentation** Short doc in the folder where objects should be located. **Test Plan** Added unit test in RELEASE_WITH_EXPENSIVE_TESTS. Pull Request resolved: #5275 Reviewed By: shajrawi Differential Revision: D26693270 Pulled By: opti-mix fbshipit-source-id: 6b57e2a56aba238ff673172ec7c352be1dcc0f84
1 parent 0b83e56 commit 2b203ab

File tree

21 files changed

+452
-3
lines changed

21 files changed

+452
-3
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is extra bundle object file for testing!

.circleci/test.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ run_and_check_bundle_with_multiple_entries() {
6868
cd -
6969
}
7070

71+
run_and_check_bundle_with_extra_objects() {
72+
cd "${GLOW_BUILD_DIR}/bundles/bundle_with_extra_objects/"
73+
# Compare console output.
74+
./BundleWithExtraObjects >> raw_results.txt
75+
diff raw_results.txt "${GLOW_SRC}/.ci/bundle_with_extra_objects_expected_output.txt"
76+
cd -
77+
}
78+
7179
run_pytorch_tests() {
7280
cd "${GLOW_SRC}/torch_glow"
7381
if hash sccache 2>/dev/null; then
@@ -113,6 +121,7 @@ case ${CIRCLE_JOB} in
113121
run_and_check_resnet50_bundle
114122
run_and_check_bundle_instrument
115123
run_and_check_bundle_with_multiple_entries
124+
run_and_check_bundle_with_extra_objects
116125
;;
117126
COVERAGE)
118127
cd "${GLOW_SRC}"

cmake/modules/GlowSerialize.cmake

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Copyright (c) Glow Contributors. See CONTRIBUTORS file.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
#===============================================================================
16+
# DESCRIPTION:
17+
# CMake utility function used to serialize as C/C++ binary data arrays all the
18+
# given input files into a given output directory and generate a C/C++ include
19+
# file which defines a std::vector variable with buffer references defined as
20+
# llvm::MemoryBufferRef. The output file is generated while running CMake but
21+
# the serialization is done during the build. All the given files must have
22+
# unique names and the names (without extension) must be valid C identifiers.
23+
#
24+
# ARGUMENTS:
25+
# INP_FILES List with input file paths (absolute paths). (MANDATORY)
26+
# OUT_DIR Output directory where files are serialized. (MANDATORY)
27+
# OUT_FILE Output C/C++ file path. (absolute path). (MANDATORY)
28+
# OUT_VAR The name of the vector variable from the output file which
29+
# holds the references for all the memory buffers. (MANDATORY)
30+
# OUT_TARGET The name of the custom output target. This target will be
31+
# used as dependency for other targets using the byproducts of
32+
# the serialization. (MANDATORY)
33+
#===============================================================================
34+
function(glow_serialize)
35+
36+
# Parse arguments (arguments are concatenated with an "ARG_" prefix).
37+
set(oneValueArgs OUT_DIR OUT_FILE OUT_VAR OUT_TARGET)
38+
set(multiValueArgs INP_FILES)
39+
cmake_parse_arguments("ARG" "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
40+
41+
# Check function parameters.
42+
# We do not check "ARG_INP_FILES" since it is allowed to be empty.
43+
44+
if (NOT ARG_OUT_DIR)
45+
message(FATAL_ERROR "OUT_DIR argument is mandatory!")
46+
endif()
47+
48+
if (NOT ARG_OUT_FILE)
49+
message(FATAL_ERROR "OUT_FILE argument is mandatory!")
50+
endif()
51+
52+
if (NOT ARG_OUT_VAR)
53+
message(FATAL_ERROR "OUT_VAR argument is mandatory!")
54+
endif()
55+
56+
if (NOT ARG_OUT_TARGET)
57+
message(FATAL_ERROR "OUT_TARGET argument is mandatory!")
58+
endif()
59+
60+
# Make output directory to serialize files.
61+
file(MAKE_DIRECTORY ${ARG_OUT_DIR})
62+
63+
# List with serialized files.
64+
set(OUT_FILES)
65+
66+
# Iterate all the input files.
67+
file(WRITE ${ARG_OUT_FILE} "// Auto-generated file. Do not edit!\n\n")
68+
foreach(inp_file ${ARG_INP_FILES})
69+
70+
# Get input file path fields.
71+
get_filename_component(file_name ${inp_file} NAME)
72+
get_filename_component(file_name_we ${inp_file} NAME_WE)
73+
message(STATUS "Serializing file: ${inp_file}")
74+
75+
# Write C/C++ code for file serialization.
76+
file(APPEND ${ARG_OUT_FILE} "static const unsigned char ${file_name_we}_data[] = {\n")
77+
file(APPEND ${ARG_OUT_FILE} " #include \"${file_name}.inc\"\n")
78+
file(APPEND ${ARG_OUT_FILE} "};\n\n")
79+
80+
# Output file path.
81+
set(out_file "${ARG_OUT_DIR}/${file_name}.inc")
82+
list(APPEND OUT_FILES ${out_file})
83+
84+
# Add command to serialize file to text.
85+
add_custom_command(
86+
OUTPUT ${out_file}
87+
COMMAND include-bin "${inp_file}" "${out_file}"
88+
DEPENDS ${inp_file}
89+
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
90+
)
91+
92+
endforeach()
93+
94+
# Create vector with buffers defined as llvm::MemoryBufferRef objects.
95+
file(APPEND ${ARG_OUT_FILE} "#define MEM_BUFF_REF(name, data) llvm::MemoryBufferRef(llvm::StringRef(reinterpret_cast<const char *>(data), sizeof(data)), name)\n\n")
96+
file(APPEND ${ARG_OUT_FILE} "static const std::vector<llvm::MemoryBufferRef> ${ARG_OUT_VAR} = {\n")
97+
foreach(inp_file ${ARG_INP_FILES})
98+
get_filename_component(file_name ${inp_file} NAME)
99+
get_filename_component(file_name_we ${inp_file} NAME_WE)
100+
file(APPEND ${ARG_OUT_FILE} " MEM_BUFF_REF(\"${file_name}\", ${file_name_we}_data),\n")
101+
endforeach()
102+
file(APPEND ${ARG_OUT_FILE} "};\n\n")
103+
file(APPEND ${ARG_OUT_FILE} "#undef MEM_BUFF_REF\n")
104+
105+
# Add custom target for serialization.
106+
add_custom_target(
107+
${ARG_OUT_TARGET}
108+
DEPENDS ${OUT_FILES}
109+
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
110+
)
111+
112+
endfunction()

examples/bundles/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ if (GLOW_WITH_BUNDLES)
22
add_subdirectory(lenet_mnist)
33
add_subdirectory(resnet50)
44
add_subdirectory(bundle_with_multiple_entries)
5+
add_subdirectory(bundle_with_extra_objects)
56
add_subdirectory(bundle_instrument)
67
endif()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
!*.o
2+
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${GLOW_BINARY_DIR}/bundles)
2+
set(LENET_MNIST_BUNDLE_DIR ${GLOW_BINARY_DIR}/examples/bundles/bundle_with_extra_objects)
3+
set(LENET_MNIST_GLOW_S3 "http://fb-glow-assets.s3.amazonaws.com/models/lenet_mnist")
4+
set(LENET_MNIST_NET_FILES predict_net.pbtxt predict_net.pb init_net.pb)
5+
set(MODEL_INPUT_NAME "data")
6+
set(IMAGES ${GLOW_SOURCE_DIR}/tests/images/mnist)
7+
8+
# Output directory.
9+
set(BUNDLE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/bundle_with_extra_objects)
10+
add_custom_target(BundleWithExtraObjectsDir ALL
11+
COMMAND ${CMAKE_COMMAND} -E make_directory ${BUNDLE_OUTPUT_DIRECTORY}
12+
)
13+
14+
# Executable.
15+
add_executable(BundleWithExtraObjects $<TARGET_OBJECTS:BundleWithExtraObjectsMain>)
16+
set_target_properties(BundleWithExtraObjects PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUNDLE_OUTPUT_DIRECTORY})
17+
target_link_libraries(BundleWithExtraObjects ${BUNDLE_OUTPUT_DIRECTORY}/lenet_mnist.o)
18+
add_dependencies(BundleWithExtraObjects BundleWithExtraObjectsMain BundleWithExtraObjectsNet)
19+
20+
# Bundle.
21+
add_custom_command(
22+
OUTPUT
23+
${BUNDLE_OUTPUT_DIRECTORY}/lenet_mnist.o
24+
COMMAND
25+
model-compiler -model=${LENET_MNIST_BUNDLE_DIR}/lenet_mnist
26+
-model-input=${MODEL_INPUT_NAME},float,[1,1,28,28]
27+
-backend=CPU -emit-bundle=${BUNDLE_OUTPUT_DIRECTORY}
28+
-bundle-api=static
29+
-bundle-objects=test.o
30+
DEPENDS
31+
model-compiler BundleWithExtraObjectsDir
32+
)
33+
add_custom_target(BundleWithExtraObjectsNet DEPENDS ${BUNDLE_OUTPUT_DIRECTORY}/lenet_mnist.o BundleWithExtraObjectsNetFiles)
34+
35+
# Driver program with main function for regular bundle
36+
add_library(BundleWithExtraObjectsMain OBJECT main.cpp)
37+
target_compile_options(BundleWithExtraObjectsMain PRIVATE -std=c++11 -g)
38+
target_include_directories(BundleWithExtraObjectsMain PUBLIC ${BUNDLE_OUTPUT_DIRECTORY})
39+
add_dependencies(BundleWithExtraObjectsMain BundleWithExtraObjectsNet)
40+
41+
# Network structure and weight files
42+
foreach(file ${LENET_MNIST_NET_FILES})
43+
add_custom_command(
44+
OUTPUT
45+
${file}
46+
COMMAND
47+
wget
48+
ARGS
49+
"${LENET_MNIST_GLOW_S3}/${file}" -P ${LENET_MNIST_BUNDLE_DIR}/lenet_mnist -nc
50+
)
51+
endforeach()
52+
add_custom_target(BundleWithExtraObjectsNetFiles DEPENDS ${LENET_MNIST_NET_FILES})
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) Glow Contributors. See CONTRIBUTORS file.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <stdio.h>
18+
19+
// String variable provided in the extra object archive with the main bundle.
20+
// The variable has C linkage.
21+
#ifdef __cplusplus
22+
extern "C" {
23+
#endif
24+
extern const char *testMsg;
25+
#ifdef __cplusplus
26+
}
27+
#endif
28+
29+
int main() { printf("%s", testMsg); }
Binary file not shown.

include/glow/Backend/Backend.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "glow/Support/Register.h"
2626

2727
#include "llvm/ADT/StringRef.h"
28+
#include "llvm/Support/MemoryBuffer.h"
2829

2930
#if FACEBOOK_INTERNAL
3031
namespace folly {
@@ -276,6 +277,16 @@ class Backend : public Named {
276277
return false;
277278
};
278279

280+
/// \returns an array of raw objects which are statically allocated and
281+
/// initialized by the backend and which can be used for various purposes,
282+
/// for example to store object files (binary code) which are compiled with
283+
/// other compilers than clang/LLVM. The raw buffers are encoded as type
284+
/// MemoryBufferRef which stores for each buffer a name, a raw pointer
285+
/// and a size (in bytes).
286+
virtual llvm::ArrayRef<llvm::MemoryBufferRef> getObjectRegistry() const {
287+
return llvm::ArrayRef<llvm::MemoryBufferRef>();
288+
}
289+
279290
protected:
280291
/// Parses the graph \F and builds a TraceInfo structure from any found
281292
/// TraceEventNodes.

include/glow/LLVMIRCodeGen/BundleSaver.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ class BundleSaver {
6161
protected:
6262
/// Perform memory allocation for a bundle.
6363
virtual void performBundleMemoryAllocation();
64+
/// Create bundle archive by archiving additional object files to the existing
65+
/// bundle from \p bundlePath. The object names to be archived are given by
66+
/// \p bundleObjects and the object raw content is taken from the object array
67+
/// \p bundleObjectRegistry.
68+
virtual void createBundleArchive(
69+
llvm::StringRef bundlePath,
70+
llvm::ArrayRef<llvm::MemoryBufferRef> bundleObjectRegistry,
71+
const std::vector<std::string> &bundleObjects);
6472
/// Save weights for the bundle.
6573
virtual void saveWeights(llvm::StringRef weightsFileName);
6674
/// Save header file for the bundle.

0 commit comments

Comments
 (0)