Skip to content

Commit c11cc93

Browse files
committed
feat(zfile): add Intel QAT hardware acceleration for LZ4 decompression
1 parent 14043c2 commit c11cc93

7 files changed

Lines changed: 670 additions & 179 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ If you want to use avx512 to accelerate CRC calculation.
111111
cmake -D ENABLE_ISAL=1 ..
112112
```
113113

114-
If you want to use QAT to accelerate compression/decompression.
114+
If you want to use QAT to accelerate compression/decompression.However, currently only the decompression part has been integrated. Since LZ4 is already a highly efficient compression algorithm, our tests show that QAT can only outperform the CPU at a 4KB block size and a batch size of 256 when the compression ratio significantly exceeds a threshold.
115115

116116
```bash
117117
cmake -D ENABLE_QAT=1 ..

src/overlaybd/zfile/CMakeLists.txt

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
file(GLOB SOURCE_ZFILE "*.cpp")
2-
file(GLOB SOURCE_LZ4 "lz4/*.c")
2+
file(GLOB SOURCE_LZ4 "lz4/*.c" "lz4/*.cpp")
33
file(GLOB SOURCE_CRC32 "crc32/crc32c.cpp")
44

55
set (CMAKE_CXX_STANDARD 17)
@@ -38,13 +38,33 @@ if(ENABLE_DSA OR ENABLE_ISAL)
3838
endif()
3939
set (CMAKE_CXX_STANDARD 14)
4040

41+
# ---- QAT auto-detection ----
42+
if (ENABLE_QAT)
43+
find_path(QAT_INCLUDE_DIR NAMES qat/cpa.h
44+
PATHS /usr/include/qat /usr/local/include/qat)
45+
find_library(QAT_LIBRARY NAMES qat)
46+
find_library(USDM_LIBRARY NAMES usdm)
47+
if (QAT_INCLUDE_DIR AND QAT_LIBRARY AND USDM_LIBRARY)
48+
message(STATUS "QAT acceleration: ENABLED (include=${QAT_INCLUDE_DIR})")
49+
else()
50+
message(WARNING "ENABLE_QAT=ON but QAT headers/libs not found; disabling QAT")
51+
set(ENABLE_QAT OFF)
52+
endif()
53+
endif()
54+
if (NOT ENABLE_QAT)
55+
# When QAT is off, exclude lz4-qat.cpp so we don't need QAT headers at all
56+
list(REMOVE_ITEM SOURCE_LZ4 "${CMAKE_CURRENT_SOURCE_DIR}/lz4/lz4-qat.cpp")
57+
message(STATUS "QAT acceleration: DISABLED")
58+
endif()
59+
# --------------------------------
60+
4161
add_library(zfile_lib STATIC ${SOURCE_ZFILE} ${SOURCE_LZ4})
4262
target_link_libraries(zfile_lib photon_static crc32_lib ${LIBZSTD})
4363

4464
if (ENABLE_QAT)
4565
target_compile_definitions(zfile_lib PUBLIC -DENABLE_QAT)
46-
target_link_libraries(zfile_lib -lpthread -lpci)
47-
#target_link_libraries(zfile_lib -lqat_s -lusdm_drv_s -lpthread -lpci)
66+
target_include_directories(zfile_lib PUBLIC ${QAT_INCLUDE_DIR})
67+
target_link_libraries(zfile_lib ${QAT_LIBRARY} ${USDM_LIBRARY} -lpci -lpthread)
4868
endif()
4969

5070
if (BUILD_TESTING)

src/overlaybd/zfile/compressor.cpp

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#ifdef ENABLE_QAT
2828
#include "lz4/lz4-qat.h"
29+
#include <atomic>
2930
extern "C" {
3031
#include <pci/pci.h>
3132
}
@@ -37,7 +38,11 @@ namespace ZFile {
3738

3839
#define QAT_VENDOR_ID 0x8086
3940
#define QAT_DEVICE_ID 0x4940
40-
41+
#ifdef ENABLE_QAT
42+
/* 0 = unprobed; 1 = available; 2 = unavailable. Cached process-wide so repeat
43+
* LZ4Compressor::init calls skip PCI scan + qat_init when QAT is absent. */
44+
static std::atomic<int> g_qat_state{0};
45+
#endif
4146
class BaseCompressor : public ICompressor {
4247
public:
4348
uint32_t max_dst_size = 0;
@@ -147,21 +152,28 @@ class LZ4Compressor : public BaseCompressor {
147152

148153
bool check_qat() {
149154
#ifdef ENABLE_QAT
150-
struct pci_access *pacc;
151-
struct pci_dev *dev;
152-
pacc = pci_alloc();
155+
int cached = g_qat_state.load(std::memory_order_acquire);
156+
if (cached == 1) return true;
157+
if (cached == 2) return false;
158+
159+
struct pci_access *pacc = pci_alloc();
160+
if (!pacc) {
161+
g_qat_state.store(2, std::memory_order_release);
162+
return false;
163+
}
153164
pci_init(pacc);
154165
pci_scan_bus(pacc);
155-
for (dev = pacc->devices; dev; dev = dev->next) {
166+
bool found = false;
167+
for (struct pci_dev *dev = pacc->devices; dev; dev = dev->next) {
156168
pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES);
157169
if (dev->vendor_id == QAT_VENDOR_ID && dev->device_id == QAT_DEVICE_ID) {
158-
pci_cleanup(pacc);
159-
return true;
170+
found = true;
171+
break;
160172
}
161173
}
162174
pci_cleanup(pacc);
163-
164-
return false;
175+
if (!found) g_qat_state.store(2, std::memory_order_release);
176+
return found;
165177
#endif
166178
return false;
167179
}
@@ -180,15 +192,23 @@ class LZ4Compressor : public BaseCompressor {
180192
#ifdef ENABLE_QAT
181193
if (check_qat()) {
182194
pQat = new LZ4_qat_param();
183-
qat_init(pQat);
184-
qat_enable = true;
195+
if (qat_init(pQat) == 0) {
196+
qat_enable = true;
197+
g_qat_state.store(1, std::memory_order_release);
198+
/* nbatch() now returns DEFAULT_N_BATCH (was 1 when BaseCompressor::init ran). */
199+
compressed_data.resize(DEFAULT_N_BATCH);
200+
uncompressed_data.resize(DEFAULT_N_BATCH);
201+
} else {
202+
delete pQat;
203+
pQat = nullptr;
204+
g_qat_state.store(2, std::memory_order_release);
205+
}
185206
}
186207
#endif
187208
return 0;
188209
}
189210

190211
int nbatch() override {
191-
// return DEFAULT_N_BATCH;
192212
return (qat_enable ? DEFAULT_N_BATCH : 1);
193213
}
194214

@@ -197,13 +217,13 @@ class LZ4Compressor : public BaseCompressor {
197217

198218
int ret = 0;
199219
#ifdef ENABLE_QAT
200-
if (qat_enable) {
201-
ret = LZ4_compress_qat(pQat, &raw_data[0], src_chunk_len, &compressed_data[0],
202-
dst_chunk_len, n);
203-
if (ret < 0) {
204-
LOG_ERROR_RETURN(EFAULT, -1, "LZ4 compress data failed. (retcode: `).", ret);
205-
}
206-
return ret;
220+
if (qat_enable) {
221+
/* dst_chunk_len in = capacity, out = actual compressed bytes. */
222+
for (size_t i = 0; i < nblock; i++) dst_chunk_len[i] = dst_buffer_capacity / nblock;
223+
ret = LZ4_compress_qat(pQat, &uncompressed_data[0], src_chunk_len,
224+
&compressed_data[0], dst_chunk_len, nblock);
225+
if (ret == 0) return 0;
226+
/* Any QAT failure falls through to the CPU loop below. */
207227
}
208228
#endif
209229
for (size_t i = 0; i < nblock; i++) {
@@ -230,12 +250,12 @@ class LZ4Compressor : public BaseCompressor {
230250
int ret = 0;
231251
#ifdef ENABLE_QAT
232252
if (qat_enable) {
253+
/* dst_chunk_len in = capacity, out = actual decompressed bytes. */
254+
for (size_t i = 0; i < n; i++) dst_chunk_len[i] = dst_buffer_capacity / n;
233255
ret = LZ4_decompress_qat(pQat, &compressed_data[0], src_chunk_len,
234256
&uncompressed_data[0], dst_chunk_len, n);
235-
if (ret < 0) {
236-
LOG_ERROR_RETURN(EFAULT, -1, "LZ4 decompress data failed. (retcode: `).", ret);
237-
}
238-
return ret;
257+
if (ret == 0) return 0;
258+
/* Any QAT failure falls through to the CPU loop below; not duplicated in lz4-qat. */
239259
}
240260
#endif
241261
for (size_t i = 0; i < n; i++) {

src/overlaybd/zfile/lz4/lz4-qat.c

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)