This is an automated email from the ASF dual-hosted git repository.

marin-ma pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gluten.git


The following commit(s) were added to refs/heads/main by this push:
     new 204b8d7128 [VL] Unify gpu hash shuffle writer output (#12499)
204b8d7128 is described below

commit 204b8d71288a7f709e22331d28f704fc4cb78593
Author: Rong Ma <[email protected]>
AuthorDate: Wed Jul 15 14:16:00 2026 +0100

    [VL] Unify gpu hash shuffle writer output (#12499)
---
 cpp/core/jni/JniWrapper.cc                   |  2 +-
 cpp/velox/CMakeLists.txt                     |  1 -
 cpp/velox/memory/GpuBufferColumnarBatch.cc   | 73 ++++++++++++++++++++--------
 cpp/velox/shuffle/VeloxGpuShuffleWriter.cc   | 72 ---------------------------
 cpp/velox/shuffle/VeloxGpuShuffleWriter.h    | 57 ----------------------
 cpp/velox/shuffle/VeloxShuffleWriter.cc      |  9 +---
 cpp/velox/tests/VeloxGpuShuffleWriterTest.cc |  5 +-
 7 files changed, 57 insertions(+), 162 deletions(-)

diff --git a/cpp/core/jni/JniWrapper.cc b/cpp/core/jni/JniWrapper.cc
index 29036132a4..a01b6a8d0a 100644
--- a/cpp/core/jni/JniWrapper.cc
+++ b/cpp/core/jni/JniWrapper.cc
@@ -1048,7 +1048,7 @@ JNIEXPORT jlong JNICALL 
Java_org_apache_gluten_vectorized_ShuffleWriterJniWrappe
   }
   ObjectStore::release(partitionWriterHandle);
 
-  auto shuffleWriterOptions = std::make_shared<GpuHashShuffleWriterOptions>(
+  auto shuffleWriterOptions = std::make_shared<HashShuffleWriterOptions>(
       toPartitioning(jStringToCString(env, partitioningNameJstr)),
       startPartitionId,
       splitBufferSize,
diff --git a/cpp/velox/CMakeLists.txt b/cpp/velox/CMakeLists.txt
index b9cffc92fa..636b073045 100644
--- a/cpp/velox/CMakeLists.txt
+++ b/cpp/velox/CMakeLists.txt
@@ -227,7 +227,6 @@ if(ENABLE_GPU)
     operators/plannodes/CudfVectorStream.cc
     shuffle/VeloxGpuAsyncShuffleReader.cc
     shuffle/VeloxGpuShuffleReader.cc
-    shuffle/VeloxGpuShuffleWriter.cc
     operators/serializer/VeloxGpuColumnarBatchSerializer.cc
     utils/GpuBufferBatchResizer.cc
     memory/GpuBufferColumnarBatch.cc)
diff --git a/cpp/velox/memory/GpuBufferColumnarBatch.cc 
b/cpp/velox/memory/GpuBufferColumnarBatch.cc
index b76a849c82..eab90eb2f8 100644
--- a/cpp/velox/memory/GpuBufferColumnarBatch.cc
+++ b/cpp/velox/memory/GpuBufferColumnarBatch.cc
@@ -28,7 +28,7 @@
 
 namespace gluten {
 namespace {
-enum class BufferType { kNull, kLength, kValue };
+enum class BufferType { kNull, kLength, kValue, kBooleanValue, kTimestampValue 
};
 }
 
 using namespace facebook;
@@ -67,16 +67,20 @@ std::shared_ptr<GpuBufferColumnarBatch> 
GpuBufferColumnarBatch::compose(
   GLUTEN_CHECK(!batches.empty(), "No batches to compose");
   // Compute the returned GpuBufferColumnarBatch buffers.
   auto& type = batches[0]->getRowType();
-  const auto bufferSize = batches[0]->buffers().size();
+  const auto numBuffers = batches[0]->buffers().size();
   std::vector<size_t> bufferSizes;
-  bufferSizes.resize(bufferSize);
+  bufferSizes.resize(numBuffers);
   std::vector<BufferType> bufferTypes;
-  bufferTypes.reserve(bufferSize);
+  bufferTypes.reserve(numBuffers);
 
   for (const auto& colType : type->children()) {
     bufferSizes[bufferTypes.size()] = arrow::bit_util::BytesForBits(numRows);
     bufferTypes.push_back(BufferType::kNull);
-    if (colType->isFixedWidth()) {
+    if (colType->isTimestamp()) {
+      bufferTypes.push_back(BufferType::kTimestampValue);
+    } else if (colType->isBoolean()) {
+      bufferTypes.push_back(BufferType::kBooleanValue);
+    } else if (colType->isFixedWidth()) {
       bufferTypes.push_back(BufferType::kValue);
     } else {
       // Add the first offset 0.
@@ -86,27 +90,37 @@ std::shared_ptr<GpuBufferColumnarBatch> 
GpuBufferColumnarBatch::compose(
       bufferTypes.push_back(BufferType::kValue);
     }
   }
-  VELOX_CHECK_EQ(bufferTypes.size(), bufferSize);
+  VELOX_CHECK_EQ(bufferTypes.size(), numBuffers);
   // This buffer may be more than the actual reauired buffer for null buffer.
   for (const auto& batch : batches) {
     if (batch->numRows() == 0) {
       continue;
     }
-    for (auto i = 0; i < bufferSize; ++i) {
+    for (auto i = 0; i < numBuffers; ++i) {
       // The null buffer may be null or length = 0.
       // Maybe optimize later, detect if the null buffer is all true. And set 
the return null buffer to 0.
       if (bufferTypes[i] == BufferType::kNull || bufferTypes[i] == 
BufferType::kLength) {
         continue;
       }
+
       auto& buffer = batch->bufferAt(i);
       VELOX_CHECK_NOT_NULL(buffer);
-      bufferSizes[i] += buffer->size();
+
+      if (bufferTypes[i] == BufferType::kTimestampValue) {
+        // Velox Timestamp value is 16 bytes. CUDF Timestamp value is 8 bytes.
+        bufferSizes[i] += static_cast<size_t>(batch->numRows()) * 
sizeof(int64_t);
+      } else if (bufferTypes[i] == BufferType::kBooleanValue) {
+        // Velox Boolean value is 1 bit. CUDF Boolean value is 1 byte.
+        bufferSizes[i] += batch->numRows();
+      } else {
+        bufferSizes[i] += buffer->size();
+      }
     }
   }
 
   std::vector<std::shared_ptr<arrow::Buffer>> returnBuffers;
-  returnBuffers.reserve(bufferSize);
-  for (auto i = 0; i < bufferSize; ++i) {
+  returnBuffers.reserve(numBuffers);
+  for (auto i = 0; i < numBuffers; ++i) {
     // Defer the null buffer to really contains null.
     if (bufferTypes[i] == BufferType::kNull) {
       returnBuffers.emplace_back(nullptr);
@@ -121,8 +135,8 @@ std::shared_ptr<GpuBufferColumnarBatch> 
GpuBufferColumnarBatch::compose(
   int32_t bufferIdx = 0;
   for (const auto& colType : type->children()) {
     size_t rowNumber = 0;
-    // Also records the value buffer offset.
-    size_t stringOffset = 0;
+    // Also records the length buffer offset for strings.
+    size_t valueBufferOffset = 0;
     for (auto i = 0; i < batches.size(); ++i) {
       const auto& batch = batches[i];
       if (batch->numRows() == 0) {
@@ -147,28 +161,47 @@ std::shared_ptr<GpuBufferColumnarBatch> 
GpuBufferColumnarBatch::compose(
         arrow::internal::CopyBitmap(batch->bufferAt(bufferIdx)->data(), 0, 
batch->numRows(), dst, rowNumber);
       }
 
-      if (colType->isFixedWidth()) {
+      if (colType->isTimestamp()) {
+        const auto bufferSize = batch->numRows() * sizeof(int64_t);
+        VELOX_CHECK_LE(valueBufferOffset + bufferSize, returnBuffers[bufferIdx 
+ 1]->size());
+        const auto* src = reinterpret_cast<const 
int64_t*>(batch->bufferAt(bufferIdx + 1)->data());
+        auto* dst = reinterpret_cast<int64_t*>(returnBuffers[bufferIdx + 
1]->mutable_data() + valueBufferOffset);
+        for (auto j = 0; j < batch->numRows(); ++j) {
+          // src[0] is seconds, src[1] is nanoseconds in Timestamp.
+          dst[j] = src[j << 1] * 1'000'000'000L + src[j << 1 | 1];
+        }
+        valueBufferOffset += bufferSize;
+      } else if (colType->isBoolean()) {
+        const auto bufferSize = batch->numRows();
+        VELOX_CHECK_LE(valueBufferOffset + bufferSize, returnBuffers[bufferIdx 
+ 1]->size());
+        const auto* src = batch->bufferAt(bufferIdx + 1)->data();
+        auto* dst = returnBuffers[bufferIdx + 1]->mutable_data() + 
valueBufferOffset;
+        for (auto j = 0; j < batch->numRows(); ++j) {
+          dst[j] = (src[j >> 3] >> (j & 7)) & 1;
+        }
+        valueBufferOffset += bufferSize;
+      } else if (colType->isFixedWidth()) {
         // The buffer is values.
         const auto bufferSize = batch->bufferAt(bufferIdx + 1)->size();
-        VELOX_CHECK_LE(stringOffset + bufferSize, returnBuffers[bufferIdx + 
1]->size());
+        VELOX_CHECK_LE(valueBufferOffset + bufferSize, returnBuffers[bufferIdx 
+ 1]->size());
         memcpy(
-            returnBuffers[bufferIdx + 1]->mutable_data() + stringOffset,
+            returnBuffers[bufferIdx + 1]->mutable_data() + valueBufferOffset,
             batch->bufferAt(bufferIdx + 1)->data(),
             bufferSize);
-        stringOffset += bufferSize;
+        valueBufferOffset += bufferSize;
       } else {
         // String, lengths, values
         memcpy(
-            returnBuffers[bufferIdx + 2]->mutable_data() + stringOffset,
+            returnBuffers[bufferIdx + 2]->mutable_data() + valueBufferOffset,
             batch->bufferAt(bufferIdx + 2)->data(),
             batch->bufferAt(bufferIdx + 2)->size());
         const auto* lengths = reinterpret_cast<const 
int32_t*>(batch->bufferAt(bufferIdx + 1)->data());
         auto* offsetBuffer = 
reinterpret_cast<int32_t*>(returnBuffers[bufferIdx + 1]->mutable_data());
         for (auto j = 0; j < batch->numRows(); ++j) {
-          offsetBuffer[rowNumber + j] = stringOffset;
-          stringOffset += lengths[j];
+          offsetBuffer[rowNumber + j] = valueBufferOffset;
+          valueBufferOffset += lengths[j];
         }
-        offsetBuffer[rowNumber + batch->numRows()] = stringOffset;
+        offsetBuffer[rowNumber + batch->numRows()] = valueBufferOffset;
       }
       rowNumber += batch->numRows();
     }
diff --git a/cpp/velox/shuffle/VeloxGpuShuffleWriter.cc 
b/cpp/velox/shuffle/VeloxGpuShuffleWriter.cc
deleted file mode 100644
index 1df6cb91ad..0000000000
--- a/cpp/velox/shuffle/VeloxGpuShuffleWriter.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-#include "VeloxGpuShuffleWriter.h"
-
-namespace gluten {
-
-// Split bool bit to bytes.
-void VeloxGpuHashShuffleWriter::splitBoolValueType(const uint8_t* srcAddr, 
const std::vector<uint8_t*>& dstAddrs) {
-  for (auto& pid : partitionUsed_) {
-    auto dstaddr = dstAddrs[pid];
-    if (dstaddr == nullptr) {
-      continue;
-    }
-    auto dstPidBase = reinterpret_cast<uint8_t*>(dstaddr + 
partitionBufferBase_[pid] * sizeof(uint8_t));
-    auto pos = partition2RowOffsetBase_[pid];
-    auto end = partition2RowOffsetBase_[pid + 1];
-    for (; pos < end; ++pos) {
-      auto rowId = rowOffset2RowId_[pos];
-      // === Extract one bool value from the bit-packed source ===
-      uint8_t byte = srcAddr[rowId >> 3]; // find the source byte
-      uint8_t bit = (byte >> (rowId & 7)) & 0x01; // extract 0 or 1
-      *dstPidBase++ = bit; // copy
-    }
-  }
-}
-
-// Split timestamp from int128_t to int64_t, both of them represents the 
timestamp nanoseconds.
-arrow::Status VeloxGpuHashShuffleWriter::splitTimestamp(const uint8_t* 
srcAddr, const std::vector<uint8_t*>& dstAddrs) {
-  for (auto& pid : partitionUsed_) {
-    auto dstPidBase = reinterpret_cast<int64_t*>(dstAddrs[pid] + 
partitionBufferBase_[pid] * sizeof(int64_t));
-    auto pos = partition2RowOffsetBase_[pid];
-    auto end = partition2RowOffsetBase_[pid + 1];
-    for (; pos < end; ++pos) {
-      auto rowId = rowOffset2RowId_[pos];
-      auto* src = reinterpret_cast<const int64_t*>(srcAddr) + rowId * 2;
-      // src[0] is seconds, src[1] is nanoseconds in Timestamp.
-      *dstPidBase++ = src[0] * 1'000'000'000LL + src[1];
-    }
-  }
-  return arrow::Status::OK();
-}
-
-arrow::Result<std::shared_ptr<VeloxShuffleWriter>> 
VeloxGpuHashShuffleWriter::create(
-    uint32_t numPartitions,
-    const std::shared_ptr<PartitionWriter>& partitionWriter,
-    const std::shared_ptr<ShuffleWriterOptions>& options,
-    MemoryManager* memoryManager) {
-  if (auto hashOptions = 
std::dynamic_pointer_cast<GpuHashShuffleWriterOptions>(options)) {
-    std::shared_ptr<VeloxGpuHashShuffleWriter> res =
-        std::make_shared<VeloxGpuHashShuffleWriter>(numPartitions, 
partitionWriter, hashOptions, memoryManager);
-    RETURN_NOT_OK(res->init());
-    return res;
-  }
-  return arrow::Status::Invalid("Error casting ShuffleWriterOptions to 
GpuHashShuffleWriterOptions. ");
-}
-
-} // namespace gluten
diff --git a/cpp/velox/shuffle/VeloxGpuShuffleWriter.h 
b/cpp/velox/shuffle/VeloxGpuShuffleWriter.h
deleted file mode 100644
index e6f0e1a358..0000000000
--- a/cpp/velox/shuffle/VeloxGpuShuffleWriter.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include "VeloxHashShuffleWriter.h"
-
-namespace gluten {
-
-class VeloxGpuHashShuffleWriter : public VeloxHashShuffleWriter {
- public:
-  static arrow::Result<std::shared_ptr<VeloxShuffleWriter>> create(
-      uint32_t numPartitions,
-      const std::shared_ptr<PartitionWriter>& partitionWriter,
-      const std::shared_ptr<ShuffleWriterOptions>& options,
-      MemoryManager* memoryManager);
-
-  VeloxGpuHashShuffleWriter(
-      uint32_t numPartitions,
-      const std::shared_ptr<PartitionWriter>& partitionWriter,
-      const std::shared_ptr<GpuHashShuffleWriterOptions>& options,
-      MemoryManager* memoryManager)
-      : VeloxHashShuffleWriter(numPartitions, partitionWriter, options, 
memoryManager) {}
-
- private:
-  // Split the bool to byte.
-  void splitBoolValueType(const uint8_t* srcAddr, const std::vector<uint8_t*>& 
dstAddrs) override;
-
-  uint64_t valueBufferSizeForBool(uint32_t newSize) override {
-    return newSize;
-  }
-
-  bool boolIsBit() override {
-    return false;
-  }
-
-  arrow::Status splitTimestamp(const uint8_t* srcAddr, const 
std::vector<uint8_t*>& dstAddrs) override;
-
-  uint64_t valueBufferSizeForTimestamp(uint32_t newSize) override {
-    return sizeof(int64_t) * newSize;
-  }
-};
-} // namespace gluten
diff --git a/cpp/velox/shuffle/VeloxShuffleWriter.cc 
b/cpp/velox/shuffle/VeloxShuffleWriter.cc
index 25ed099014..a83e3a1947 100644
--- a/cpp/velox/shuffle/VeloxShuffleWriter.cc
+++ b/cpp/velox/shuffle/VeloxShuffleWriter.cc
@@ -20,10 +20,6 @@
 #include "shuffle/VeloxRssSortShuffleWriter.h"
 #include "shuffle/VeloxSortShuffleWriter.h"
 
-#ifdef GLUTEN_ENABLE_GPU
-#include "VeloxGpuShuffleWriter.h"
-#endif
-
 namespace gluten {
 
 arrow::Result<std::shared_ptr<VeloxShuffleWriter>> VeloxShuffleWriter::create(
@@ -35,15 +31,12 @@ arrow::Result<std::shared_ptr<VeloxShuffleWriter>> 
VeloxShuffleWriter::create(
   std::shared_ptr<VeloxShuffleWriter> shuffleWriter;
   switch (type) {
     case ShuffleWriterType::kHashShuffle:
+    case ShuffleWriterType::kGpuHashShuffle:
       return VeloxHashShuffleWriter::create(numPartitions, 
std::move(partitionWriter), options, memoryManager);
     case ShuffleWriterType::kSortShuffle:
       return VeloxSortShuffleWriter::create(numPartitions, 
std::move(partitionWriter), options, memoryManager);
     case ShuffleWriterType::kRssSortShuffle:
       return VeloxRssSortShuffleWriter::create(numPartitions, 
std::move(partitionWriter), options, memoryManager);
-#ifdef GLUTEN_ENABLE_GPU
-    case ShuffleWriterType::kGpuHashShuffle:
-      return VeloxGpuHashShuffleWriter::create(numPartitions, 
std::move(partitionWriter), options, memoryManager);
-#endif
     default:
       return arrow::Status::Invalid("Unsupported shuffle writer type: ", 
typeToString(type));
   }
diff --git a/cpp/velox/tests/VeloxGpuShuffleWriterTest.cc 
b/cpp/velox/tests/VeloxGpuShuffleWriterTest.cc
index cc846eb4eb..896fa9e626 100644
--- a/cpp/velox/tests/VeloxGpuShuffleWriterTest.cc
+++ b/cpp/velox/tests/VeloxGpuShuffleWriterTest.cc
@@ -20,8 +20,7 @@
 
 #include "config/GlutenConfig.h"
 #include "memory/GpuBufferColumnarBatch.h"
-#include "shuffle/VeloxGpuShuffleWriter.h"
-#include "shuffle/VeloxHashShuffleWriter.h"
+#include "shuffle/VeloxShuffleWriter.h"
 #include "tests/VeloxShuffleWriterTestBase.h"
 #include "tests/utils/TestAllocationListener.h"
 #include "tests/utils/TestStreamReader.h"
@@ -227,7 +226,7 @@ class GpuVeloxShuffleWriterTest : public 
::testing::TestWithParam<GpuShuffleTest
     const auto& params = GetParam();
     switch (params.shuffleWriterType) {
       case ShuffleWriterType::kGpuHashShuffle: {
-        auto hashOptions = std::make_shared<GpuHashShuffleWriterOptions>();
+        auto hashOptions = std::make_shared<HashShuffleWriterOptions>();
         hashOptions->splitBufferSize = splitBufferSize;
         options = hashOptions;
       } break;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to