Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 4.3k
GH-38868: [C++][Python] Add Array::ToTensor and fixed size list support#50929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+441
−113
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
032dfb6
Rename some functions
AntoinePrv 8d04ba0
Handle recursive FixedSizeList
AntoinePrv e68ce4e
Factor export device
AntoinePrv 36ac290
Factorize stride utilities
AntoinePrv 98b2a9e
Add Array::ToTensor
AntoinePrv 5261798
Add FixedSizeListArray::ToTensor
AntoinePrv f338b89
Remove DLPack support for nested list
AntoinePrv 73215e0
Add ToTensor in eror message
AntoinePrv 4e390a5
Add ToTensor in Python
AntoinePrv 862ab2d
Add dlpack to_tensor test
AntoinePrv 7957226
Remove unecessary changes
AntoinePrv 5d0d7d5
Fix test
AntoinePrv 6b55272
Build derived type in from_storage
AntoinePrv 7ce9d1f
Do not use unversionned dlpack
AntoinePrv 9791a66
Fix review comments
AntoinePrv 8de5ed7
Review round
AntoinePrv a805276
Fix test on old numpy
AntoinePrv 93ed882
Remove unecessary overflow checks
AntoinePrv 5049e06
Add allow_nulls options to ToTensor
AntoinePrv 5d46307
Add Tensor::FromArray
AntoinePrv 3093fc8
Add allow_nulls to to_tensor in Python
AntoinePrv 2a29d76
Add Python dlpack test with nulls
AntoinePrv 057a142
Add missing fwd declaration
AntoinePrv 9683d1e
Fix python wrappers
AntoinePrv ba63f3b
Fix array tests
AntoinePrv 3fb604f
Prefer TypeError
AntoinePrv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -33,13 +33,15 @@ | ||
| #include "arrow/array/util.h" | ||
| #include "arrow/buffer.h" | ||
| #include "arrow/status.h" | ||
| #include "arrow/tensor.h" | ||
| #include "arrow/type.h" | ||
| #include "arrow/type_fwd.h" | ||
| #include "arrow/type_traits.h" | ||
| #include "arrow/util/bit_util.h" | ||
| #include "arrow/util/bitmap_generate.h" | ||
| #include "arrow/util/bitmap_ops.h" | ||
| #include "arrow/util/checked_cast.h" | ||
| #include "arrow/util/int_util_overflow.h" | ||
| #include "arrow/util/list_util.h" | ||
| #include "arrow/util/logging_internal.h" | ||
| #include "arrow/util/unreachable.h" | ||
| @@ -1001,6 +1003,44 @@ Result<std::shared_ptr<Array>> FixedSizeListArray::Flatten( | ||
| return FlattenListArray(*this, memory_pool); | ||
| } | ||
| Result<std::shared_ptr<Tensor>> FixedSizeListArray::ToTensorWithNulls() const { | ||
| const auto* data = this->data().get(); | ||
| auto type = this->type(); | ||
| int64_t offset = data->offset; | ||
| int64_t length = data->length; | ||
| std::vector<int64_t> shape{length}; | ||
| // Iterate over nested fixed length container types. | ||
| // Each nested container increase the tensor dimension. | ||
| while (type->id() == Type::FIXED_SIZE_LIST) { | ||
| const auto* fsl = internal::checked_cast<const FixedSizeListType*>(type.get()); | ||
| type = fsl->value_type(); | ||
| data = data->child_data.front().get(); | ||
| // Overflow cannot happen on a valid array (its data needs to fit in memory, | ||
| // therefore be smaller than INT64_MAX) | ||
| offset = offset * fsl->list_size() + data->offset; | ||
| length = length * fsl->list_size(); | ||
| shape.push_back(fsl->list_size()); | ||
| } | ||
| // Only checking byte_width which we need here and leaving Tensor::Make error on | ||
| // unsupported types. | ||
| if (!is_fixed_width(*type)) { | ||
| return Status::TypeError("Expected a fixed width leaf type, got ", type->name()); | ||
| } | ||
| std::shared_ptr<Buffer> buffer = nullptr; | ||
| if (const auto& buf = data->buffers[1]; buf != NULLPTR) { | ||
| const int64_t byte_width = type->byte_width(); | ||
| // Buffer guarantees this fits into an int64_t. | ||
| const int64_t byte_offset = offset * byte_width; | ||
| const int64_t byte_length = length * byte_width; | ||
| ARROW_ASSIGN_OR_RAISE(buffer, SliceBufferSafe(buf, byte_offset, byte_length)); | ||
| } | ||
AntoinePrv marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| return Tensor::Make(std::move(type), std::move(buffer), std::move(shape)); | ||
| } | ||
| // ---------------------------------------------------------------------- | ||
| // Struct | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -50,6 +50,7 @@ | ||
| #include "arrow/result.h" | ||
| #include "arrow/scalar.h" | ||
| #include "arrow/status.h" | ||
| #include "arrow/tensor.h" | ||
| #include "arrow/testing/builder.h" | ||
| #include "arrow/testing/extension_type.h" | ||
| #include "arrow/testing/gtest_compat.h" | ||
| @@ -1218,6 +1219,67 @@ TEST(TestPrimitiveArray, CtorNoValidityBitmap) { | ||
| ASSERT_EQ(arr.data()->null_count, 0); | ||
| } | ||
| TEST(TestPrimitiveArray, ToTensor) { | ||
| const std::vector<int64_t> shape = {5}; | ||
| const std::vector<int64_t> strides = {sizeof(int32_t)}; | ||
| auto array = ArrayFromJSON(int32(), "[1, 2, 3, 4, 5]"); | ||
| ASSERT_OK_AND_ASSIGN(auto tensor, array->ToTensor()); | ||
| ASSERT_OK(tensor->Validate()); | ||
| EXPECT_EQ(int32(), tensor->type()); | ||
| EXPECT_EQ(shape, tensor->shape()); | ||
| EXPECT_EQ(strides, tensor->strides()); | ||
| EXPECT_TRUE(tensor->is_contiguous()); | ||
| EXPECT_TRUE( | ||
| TensorFromJSON(int32(), "[1, 2, 3, 4, 5]", shape, strides)->Equals(*tensor)); | ||
| } | ||
| TEST(TestPrimitiveArray, ToTensorSliced) { | ||
| const std::vector<int64_t> shape = {3}; | ||
| const std::vector<int64_t> strides = {sizeof(int64_t)}; | ||
| auto array = ArrayFromJSON(int64(), "[1, 2, 3, 4, 5]")->Slice(2); | ||
| ASSERT_OK_AND_ASSIGN(auto tensor, array->ToTensor()); | ||
| ASSERT_OK(tensor->Validate()); | ||
| EXPECT_EQ(shape, tensor->shape()); | ||
| EXPECT_TRUE(TensorFromJSON(int64(), "[3, 4, 5]", shape, strides)->Equals(*tensor)); | ||
| } | ||
| TEST(TestPrimitiveArray, ZeroLength) { | ||
| Int64Builder builder; | ||
| ASSERT_OK_AND_ASSIGN(auto array, builder.Finish()); | ||
| ASSERT_OK_AND_ASSIGN(auto tensor, array->ToTensor()); | ||
| ASSERT_OK(tensor->Validate()); | ||
| EXPECT_EQ(int64(), tensor->type()); | ||
| EXPECT_EQ(std::vector<int64_t>{0}, tensor->shape()); | ||
| EXPECT_EQ(std::vector<int64_t>{sizeof(int64_t)}, tensor->strides()); | ||
| } | ||
| TEST(TestPrimitiveArray, ToTensorNulls) { | ||
AntoinePrv marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| // Nulls are ignored, leaving unspecified values in the output tensor. | ||
| auto array = ArrayFromJSON(int32(), "[1, null, 3]"); | ||
| // Default behaviour is to not allow nulls | ||
| ASSERT_RAISES(Invalid, array->ToTensor()); | ||
| // Nulls are ignored, leaving unspecified values in the output tensor. | ||
| ASSERT_OK_AND_ASSIGN(auto tensor, array->ToTensor(/* allow_nulls= */ true)); | ||
| ASSERT_OK(tensor->Validate()); | ||
| ASSERT_EQ(tensor->Value<Int32Type>({0}), 1); | ||
| ASSERT_EQ(tensor->Value<Int32Type>({2}), 3); | ||
| EXPECT_EQ(std::vector<int64_t>{3}, tensor->shape()); | ||
| } | ||
| TEST(TestPrimitiveArray, ToTensorUnsupportedType) { | ||
| auto array = ArrayFromJSON(date32(), "[1, 2, 3]"); | ||
| ASSERT_RAISES(TypeError, array->ToTensor()); | ||
| ASSERT_RAISES(TypeError, ArrayFromJSON(utf8(), R"(["a"])")->ToTensor()); | ||
| } | ||
| class TestBuilder : public ::testing::Test { | ||
| protected: | ||
| MemoryPool* pool_ = default_memory_pool(); | ||
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.