Skip to content

Commit de8e26a

Browse files
committed
new feature: compress precompiled
1 parent 0e046f9 commit de8e26a

5 files changed

Lines changed: 85 additions & 11 deletions

File tree

Orochi/OrochiUtils.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
#include <sys/stat.h>
3737
#endif
3838

39+
#ifdef ORO_LINK_ZSTD
40+
#include <contrib/zstd/lib/zstd.h>
41+
#endif
42+
3943
inline std::wstring utf8_to_wstring( const std::string& str )
4044
{
4145
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> myconv;
@@ -790,3 +794,35 @@ void OrochiUtils::launch2D( oroFunction func, int nx, int ny, const void** args,
790794
OROASSERT( e == oroSuccess, 0 );
791795
}
792796

797+
void OrochiUtils::DecompressPrecompiled(std::vector<unsigned char>& out, const unsigned char* compressedInput, size_t compressedInput_sizeByte, size_t uncompressed_sizeByte)
798+
{
799+
if ( uncompressed_sizeByte > 0 ) // if the input data is actually compressed
800+
{
801+
#ifdef ORO_LINK_ZSTD
802+
out.assign(uncompressed_sizeByte,0);
803+
804+
size_t decompressedSize = ZSTD_decompress(
805+
out.data(), // final uncompressed buffer
806+
out.size(), // final size
807+
compressedInput, // compressed buffer
808+
compressedInput_sizeByte // compressed buffer - size
809+
);
810+
811+
if ( decompressedSize != uncompressed_sizeByte )
812+
throw std::runtime_error( "ERROR: ZSTD_decompress FAILED." );
813+
#else
814+
815+
throw std::runtime_error( "ERROR: ZSTD is not part of this build." );
816+
817+
#endif
818+
819+
}
820+
else // if the input data is NOT compressed, buypass this decompress process.
821+
{
822+
out = std::vector<unsigned char>(compressedInput, compressedInput + compressedInput_sizeByte );
823+
}
824+
return;
825+
}
826+
827+
828+

Orochi/OrochiUtils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class OrochiUtils
8383
static void getModule( oroDevice device, const char* code, const char* path, std::vector<const char*>* optsIn, const char* funcName, oroModule* moduleOut );
8484
static void launch1D( oroFunction func, int nx, const void** args, int wgSize = 64, unsigned int sharedMemBytes = 0, oroStream stream = 0 );
8585
static void launch2D( oroFunction func, int nx, int ny, const void** args, int wgSizeX = 8, int wgSizeY = 8, unsigned int sharedMemBytes = 0, oroStream stream = 0 );
86+
87+
// if 'uncompressed_sizeByte' is set to 0, it means the input value is not compressed and this function will output the raw buffer.
88+
static void DecompressPrecompiled(std::vector<unsigned char>& out, const unsigned char* compressedInput, size_t compressedInput_sizeByte, size_t uncompressed_sizeByte);
8689

8790
template<typename T>
8891
static void malloc( T*& ptr, size_t n )

ParallelPrimitives/RadixSort.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static const char** RadixSortKernelsIncludes = nullptr;
5454
#else
5555
const unsigned char oro_compiled_kernels_h[] = "";
5656
const size_t oro_compiled_kernels_h_size = 0;
57+
const size_t oro_compiled_kernels_h_size_uncompressed = 0;
5758
#endif
5859

5960
constexpr uint64_t div_round_up64( uint64_t val, uint64_t divisor ) noexcept { return ( val + divisor - 1 ) / divisor; }
@@ -189,8 +190,8 @@ void RadixSort::compileKernels( const std::string& kernelPath, const std::string
189190
{
190191
if constexpr( usePrecompiledAndBakedKernel )
191192
{
192-
// Move the raw buffer into a std::vector, which avoids potential issues explained here: github.com/GPUOpen-LibrariesAndSDKs/HIPRT/pull/38#issuecomment-2761698032
193-
std::vector<unsigned char> binary(oro_compiled_kernels_h, oro_compiled_kernels_h + oro_compiled_kernels_h_size);
193+
std::vector<unsigned char> binary;
194+
OrochiUtils::DecompressPrecompiled(binary, oro_compiled_kernels_h, oro_compiled_kernels_h_size, oro_compiled_kernels_h_size_uncompressed);
194195
oroFunctions[record.kernelType] = m_oroutils.getFunctionFromPrecompiledBinary_asData(binary.data(), binary.size(), record.kernelName.c_str() );
195196
}
196197
else if constexpr( useBakeKernel )

scripts/convert_binary_to_array.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,39 @@
1-
# convert_binary_to_header.py
1+
# convert_binary_to_array.py
22
import sys
33
from pathlib import Path
44

5-
def binary_to_c_array(bin_file, array_name):
5+
def binary_to_c_array(bin_file, array_name, size_BeforeCompression, compression_activated):
66
with open(bin_file, 'rb') as f:
77
binary_data = f.read()
88

99
hex_array = ', '.join(f'0x{b:02x}' for b in binary_data)
1010
c_array = f'const unsigned char {array_name}[] = {{\n {hex_array}\n}};\n'
11-
c_array += f'const size_t {array_name}_size = sizeof({array_name});\n'
11+
c_array += f'const size_t {array_name}_size = sizeof({array_name}); // {len(binary_data)}\n'
12+
13+
if not compression_activated:
14+
size_BeforeCompression = 0 # set value to 0 if we are not using compression.
15+
c_array += f'const size_t {array_name}_size_uncompressed = {size_BeforeCompression}; // set to 0 if NOT using the ZSTD compression.\n'
1216
return c_array
1317

1418
if __name__ == "__main__":
15-
if len(sys.argv) != 3:
16-
print(f"Usage: {sys.argv[0]} <input_binary_file> <output_header_file>")
19+
if len(sys.argv) != 5:
20+
print(f"Usage: {sys.argv[0]} <input_binary_file_before_compression> <input_binary_file_after_compression> <output_header_file> <compression_activated>")
1721
sys.exit(1)
1822

19-
bin_file = sys.argv[1]
20-
header_file_path = sys.argv[2]
23+
bin_file_beforeCompression = sys.argv[1]
24+
bin_file_afterCompression = sys.argv[2] # not used if 'compression_activated' is OFF
25+
header_file_path = sys.argv[3]
26+
compression_activated = sys.argv[4].lower() == "on" # sys.argv[4] should be "ON" or "OFF"
27+
2128
header_file = Path(header_file_path).name
2229
array_name = header_file.replace('.', '_')
2330

24-
c_array = binary_to_c_array(bin_file, array_name)
31+
if not compression_activated:
32+
bin_file_afterCompression = bin_file_beforeCompression
33+
34+
c_array = binary_to_c_array(bin_file_afterCompression, array_name, Path(bin_file_beforeCompression).stat().st_size, compression_activated )
2535
with open(header_file_path, 'w') as f:
26-
f.write("// generated by convert_binary_to_header.py\n")
36+
f.write("// generated by convert_binary_to_array.py\n")
37+
if compression_activated:
38+
f.write(f"// Data is compressed.\n")
2739
f.write(c_array)

scripts/create_archive.cmake

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
# create_archive.cmake
3+
# Create a raw Zstd-compressed "archive" from a single file.
4+
5+
# Variables expected:
6+
# INPUT_FILE – path to the file to compress
7+
# OUTPUT_FILE – path to the compressed file to generate
8+
# DO_COMPRESS: ON/OFF
9+
10+
11+
if(DO_COMPRESS)
12+
file(ARCHIVE_CREATE
13+
OUTPUT "${OUTPUT_FILE}"
14+
PATHS "${INPUT_FILE}"
15+
FORMAT raw
16+
COMPRESSION Zstd
17+
COMPRESSION_LEVEL 19
18+
)
19+
endif()
20+
21+
22+

0 commit comments

Comments
 (0)