kou commented on code in PR #14585:
URL: https://github.com/apache/arrow/pull/14585#discussion_r1044813741


##########
cpp/CMakeLists.txt:
##########
@@ -796,6 +796,15 @@ if(ARROW_USE_XSIMD)
   list(APPEND ARROW_STATIC_LINK_LIBS xsimd)
 endif()
 
+if(ARROW_WITH_QPL)
+  add_definitions(-DARROW_WITH_QPL)

Review Comment:
   Could you put this to `cpp/src/arrow/util/config.h.cmake` instead of here?



##########
cpp/cmake_modules/FindQPL.cmake:
##########
@@ -0,0 +1,60 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# - Find Intel®QPL
+# This module defines
+#  QPL_ROOT - When set, this path is inspected instead of standard library
+#  QPL_INCLUDE_DIR, directory containing headers
+#  QPL_STATIC_LIB, path to libqpl.a
+#  QPL_FOUND, whether QPL is found or not

Review Comment:
   We should mark only CMake target (`qpl::qpl`) public API. Others should not 
mark public API.



##########
cpp/cmake_modules/FindQPL.cmake:
##########
@@ -0,0 +1,60 @@
+# Licensed to the Apache Software Foundation (ASF) under one

Review Comment:
   Do we need this file?
   It seems that QPL provides its CMake package: 
https://github.com/intel/qpl/blob/develop/CMakeLists.txt#L66-L68



##########
cpp/cmake_modules/ThirdpartyToolchain.cmake:
##########
@@ -64,6 +64,7 @@ set(ARROW_THIRDPARTY_DEPENDENCIES
     ORC
     re2
     Protobuf
+    QPL

Review Comment:
   It seems that QPL uses `Qpl` for its CMake package name: 
https://github.com/intel/qpl/blob/develop/CMakeLists.txt#L66-L68
   
   ```suggestion
       Qpl
   ```



##########
cpp/src/arrow/util/bit_stream_utils.h:
##########
@@ -200,6 +213,7 @@ class BitReader {
 
   int byte_offset_;  // Offset in buffer_
   int bit_offset_;   // Offset in buffered_values_
+  int val_offset_;   // Index of next value to read

Review Comment:
   Please don't abbreviate `value` as `val` for readability and consistency?



##########
cpp/cmake_modules/ThirdpartyToolchain.cmake:
##########
@@ -2203,6 +2214,45 @@ if(ARROW_WITH_RAPIDJSON)
   endif()
 endif()
 
+macro(build_qpl)
+  message(STATUS "Building QPL from source")
+  set(QPL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/qpl_ep/src/qpl_ep-install")
+  set(QPL_STATIC_LIB_NAME 
${CMAKE_STATIC_LIBRARY_PREFIX}qpl${CMAKE_STATIC_LIBRARY_SUFFIX})
+  set(QPL_STATIC_LIB "${QPL_PREFIX}/lib/${QPL_STATIC_LIB_NAME}")
+  set(QPL_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} -DCMAKE_INSTALL_LIBDIR=lib
+                     "-DCMAKE_INSTALL_PREFIX=${QPL_PREFIX}")
+  set(QPL_PATCH_COMMAND
+      "sed" "-i" "17,18d"
+      
"${CMAKE_CURRENT_BINARY_DIR}/qpl_ep-prefix/src/qpl_ep/tools/CMakeLists.txt")
+
+  externalproject_add(qpl_ep
+                      ${EP_LOG_OPTIONS}
+                      URL ${QPL_SOURCE_URL}
+                      URL_HASH "SHA256=${ARROW_QPL_BUILD_SHA256_CHECKSUM}"
+                      PATCH_COMMAND ${QPL_PATCH_COMMAND}
+                      BUILD_BYPRODUCTS "${QPL_STATIC_LIB}"
+                      CMAKE_ARGS ${QPL_CMAKE_ARGS})
+
+  file(MAKE_DIRECTORY "${QPL_PREFIX}/include")
+
+  add_library(qpl::qpl STATIC IMPORTED)

Review Comment:
   Could you use `Qpl::qpl` because QPL's CMake package uses `Qpl::qpl`?



##########
cpp/cmake_modules/ThirdpartyToolchain.cmake:
##########
@@ -2203,6 +2214,45 @@ if(ARROW_WITH_RAPIDJSON)
   endif()
 endif()
 
+macro(build_qpl)
+  message(STATUS "Building QPL from source")
+  set(QPL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/qpl_ep/src/qpl_ep-install")
+  set(QPL_STATIC_LIB_NAME 
${CMAKE_STATIC_LIBRARY_PREFIX}qpl${CMAKE_STATIC_LIBRARY_SUFFIX})
+  set(QPL_STATIC_LIB "${QPL_PREFIX}/lib/${QPL_STATIC_LIB_NAME}")
+  set(QPL_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} -DCMAKE_INSTALL_LIBDIR=lib
+                     "-DCMAKE_INSTALL_PREFIX=${QPL_PREFIX}")
+  set(QPL_PATCH_COMMAND
+      "sed" "-i" "17,18d"

Review Comment:
   `sed -i` (no suffix) isn't portable. It works with GNU sed but not with BSD 
sed.
   
   BTW, this approach is too fragile. How about using `patch` command like a 
code in `build_google_cloud_cpp_storage()`?



##########
cpp/cmake_modules/ThirdpartyToolchain.cmake:
##########
@@ -633,6 +636,14 @@ else()
            
"${THIRDPARTY_MIRROR_URL}/protobuf-${ARROW_PROTOBUF_BUILD_VERSION}.tar.gz")
 endif()
 
+if(DEFINED ENV{ARROW_QPL_URL})
+  set(QPL_SOURCE_URL "$ENV{ARROW_QPL_URL}")
+else()
+  set_urls(QPL_SOURCE_URL
+           
"https://github.com/intel/qpl/archive/refs/tags/${ARROW_QPL_BUILD_VERSION}.tar.gz";
+           "${THIRDPARTY_MIRROR_URL}/qpl-${ARROW_QPL_BUILD_VERSION}.tar.gz")

Review Comment:
   We don't need a mirror URL here because we don't prepare it.
   
   ```suggestion
              
"https://github.com/intel/qpl/archive/refs/tags/${ARROW_QPL_BUILD_VERSION}.tar.gz";)
   ```



##########
cpp/src/arrow/util/rle_encoding.h:
##########
@@ -598,6 +605,83 @@ inline int RleDecoder::GetBatchWithDict(const T* 
dictionary, int32_t dictionary_
   return values_read;
 }
 
+#ifdef ARROW_WITH_QPL
+template <typename T, typename V>
+inline void CopyValues(const T* dictionary, std::vector<uint8_t>* destination, 
T* values,
+                       int batch_size) {
+  auto* out = values;
+  auto* indices = reinterpret_cast<V*>(destination->data());
+  for (int j = 0; j < batch_size; j++) {
+    auto idx = indices[j];
+    T val = dictionary[idx];
+    std::fill(out, out + 1, val);
+    out++;
+  }
+  return;
+}
+
+template <typename T>
+inline int RleDecoder::GetBatchWithDictIAA(const T* dictionary, int32_t 
dictionary_length,
+                                           T* values, int batch_size) {
+  if (batch_size <= 0) {
+    return batch_size;
+  }
+  if (!::arrow::util::internal::QplJobHWPool::GetInstance().job_ready() ||
+      bit_width_ <= 1) {
+    return GetBatchWithDict(dictionary, dictionary_length, values, batch_size);
+  }
+  uint32_t job_id = 0;
+  qpl_job* job = 
::arrow::util::internal::QplJobHWPool::GetInstance().AcquireJob(job_id);
+  if (job == NULL) {
+    return -1;
+  }
+
+  std::vector<uint8_t>* destination;
+  if (dictionary_length < 0xFF) {
+    job->out_bit_width = qpl_ow_8;
+    destination = new std::vector<uint8_t>(batch_size, 0);

Review Comment:
   Who does free this? QPL?
   Can we use `std::vector<uint8_t> destination` and `std::vector::resize()` 
instead of `new std::vector<uint8_t>`?



##########
cpp/src/arrow/util/rle_encoding.h:
##########
@@ -598,6 +605,83 @@ inline int RleDecoder::GetBatchWithDict(const T* 
dictionary, int32_t dictionary_
   return values_read;
 }
 
+#ifdef ARROW_WITH_QPL
+template <typename T, typename V>
+inline void CopyValues(const T* dictionary, std::vector<uint8_t>* destination, 
T* values,
+                       int batch_size) {
+  auto* out = values;
+  auto* indices = reinterpret_cast<V*>(destination->data());
+  for (int j = 0; j < batch_size; j++) {
+    auto idx = indices[j];
+    T val = dictionary[idx];
+    std::fill(out, out + 1, val);
+    out++;
+  }
+  return;
+}
+
+template <typename T>
+inline int RleDecoder::GetBatchWithDictIAA(const T* dictionary, int32_t 
dictionary_length,
+                                           T* values, int batch_size) {
+  if (batch_size <= 0) {
+    return batch_size;
+  }
+  if (!::arrow::util::internal::QplJobHWPool::GetInstance().job_ready() ||
+      bit_width_ <= 1) {
+    return GetBatchWithDict(dictionary, dictionary_length, values, batch_size);
+  }
+  uint32_t job_id = 0;
+  qpl_job* job = 
::arrow::util::internal::QplJobHWPool::GetInstance().AcquireJob(job_id);
+  if (job == NULL) {
+    return -1;

Review Comment:
   Should we fall back to `GetBatchWithDict()`?



##########
cpp/src/arrow/util/rle_encoding.h:
##########
@@ -598,6 +605,83 @@ inline int RleDecoder::GetBatchWithDict(const T* 
dictionary, int32_t dictionary_
   return values_read;
 }
 
+#ifdef ARROW_WITH_QPL
+template <typename T, typename V>
+inline void CopyValues(const T* dictionary, std::vector<uint8_t>* destination, 
T* values,
+                       int batch_size) {
+  auto* out = values;
+  auto* indices = reinterpret_cast<V*>(destination->data());
+  for (int j = 0; j < batch_size; j++) {
+    auto idx = indices[j];
+    T val = dictionary[idx];
+    std::fill(out, out + 1, val);
+    out++;
+  }
+  return;
+}
+
+template <typename T>
+inline int RleDecoder::GetBatchWithDictIAA(const T* dictionary, int32_t 
dictionary_length,
+                                           T* values, int batch_size) {
+  if (batch_size <= 0) {
+    return batch_size;
+  }
+  if (!::arrow::util::internal::QplJobHWPool::GetInstance().job_ready() ||
+      bit_width_ <= 1) {
+    return GetBatchWithDict(dictionary, dictionary_length, values, batch_size);
+  }
+  uint32_t job_id = 0;
+  qpl_job* job = 
::arrow::util::internal::QplJobHWPool::GetInstance().AcquireJob(job_id);

Review Comment:
   ```suggestion
     auto job = 
::arrow::util::internal::QplJobHWPool::GetInstance().AcquireJob(job_id);
   ```



##########
cpp/src/parquet/CMakeLists.txt:
##########
@@ -127,7 +127,6 @@ set(PARQUET_SHARED_TEST_LINK_LIBS arrow_testing_shared 
${PARQUET_MIN_TEST_LIBS}
 
 set(PARQUET_STATIC_TEST_LINK_LIBS ${PARQUET_MIN_TEST_LIBS} parquet_static 
thrift::thrift
                                   ${ARROW_LIBRARIES_FOR_STATIC_TESTS})
-

Review Comment:
   Could you revert this to reduce needless diff?



##########
cpp/thirdparty/versions.txt:
##########
@@ -96,7 +98,6 @@ 
ARROW_ZLIB_BUILD_SHA256_CHECKSUM=b3a24de97a8fdbc835b9833169501030b8977031bcb54b3
 ARROW_ZSTD_BUILD_VERSION=v1.5.2
 
ARROW_ZSTD_BUILD_SHA256_CHECKSUM=f7de13462f7a82c29ab865820149e778cbfe01087b3a55b5332707abf9db4a6e
 
-

Review Comment:
   Could you revert this to reduce needless diff?



##########
cpp/src/arrow/util/bit_stream_utils.h:
##########
@@ -190,6 +195,14 @@ class BitReader {
   /// Maximum byte length of a vlq encoded int64
   static constexpr int kMaxVlqByteLengthForInt64 = 10;
 
+  const uint8_t* GetBuffer() { return buffer_ - 1; }
+
+  int GetBufferLen() { return max_bytes_ + 1; }
+
+  void updateValOffset(int batch_size) { val_offset_ += batch_size; }
+
+  int GetValOffset() { return val_offset_; }

Review Comment:
   I don't think that exporting internal buffer and changing offset from 
outside is a good API.
   This is a reader class. So this is responsible to manage them. This API just 
uses this as a data container.
   
   Can we choose another approach? For example, can we use QPL in this?



##########
cpp/src/arrow/util/rle_encoding.h:
##########
@@ -598,6 +605,83 @@ inline int RleDecoder::GetBatchWithDict(const T* 
dictionary, int32_t dictionary_
   return values_read;
 }
 
+#ifdef ARROW_WITH_QPL
+template <typename T, typename V>
+inline void CopyValues(const T* dictionary, std::vector<uint8_t>* destination, 
T* values,
+                       int batch_size) {
+  auto* out = values;
+  auto* indices = reinterpret_cast<V*>(destination->data());
+  for (int j = 0; j < batch_size; j++) {
+    auto idx = indices[j];
+    T val = dictionary[idx];
+    std::fill(out, out + 1, val);
+    out++;
+  }
+  return;
+}
+
+template <typename T>
+inline int RleDecoder::GetBatchWithDictIAA(const T* dictionary, int32_t 
dictionary_length,
+                                           T* values, int batch_size) {
+  if (batch_size <= 0) {
+    return batch_size;
+  }
+  if (!::arrow::util::internal::QplJobHWPool::GetInstance().job_ready() ||
+      bit_width_ <= 1) {
+    return GetBatchWithDict(dictionary, dictionary_length, values, batch_size);
+  }
+  uint32_t job_id = 0;
+  qpl_job* job = 
::arrow::util::internal::QplJobHWPool::GetInstance().AcquireJob(job_id);
+  if (job == NULL) {

Review Comment:
   ```suggestion
     if (!job) {
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to