Skip to content

Commit 4e0aa3c

Browse files
committed
ARROW-1387: [C++] Set up GPU leaf library, add unit test module for CUDA tests
This is an optional leaf library for users who want to use Arrow data on graphics cards. See parent JIRA ARROW-1055 for a roadmap for some basic GPU extensions Author: Wes McKinney <wes.mckinney@twosigma.com> Closes apache#982 from wesm/arrow-gpu-lib and squashes the following commits: f8c00eb [Wes McKinney] Remove cruft from CMakeLists.txt e8f04a8 [Wes McKinney] Set up libarrow_gpu, add simple unit test that allocates memory on device Change-Id: Ia1851ea6f30cb7cf3de422779d2d029e4ded672f
1 parent 6ad976e commit 4e0aa3c

10 files changed

Lines changed: 383 additions & 1 deletion

File tree

cpp/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
9898
"Build the Arrow IPC extensions"
9999
ON)
100100

101+
option(ARROW_GPU
102+
"Build the Arrow GPU extensions (requires CUDA installation)"
103+
OFF)
104+
101105
option(ARROW_JEMALLOC
102106
"Build the Arrow jemalloc-based allocator"
103107
OFF)
@@ -713,6 +717,10 @@ if (ARROW_IPC)
713717
add_dependencies(arrow_dependencies metadata_fbs)
714718
endif()
715719
720+
if (ARROW_GPU)
721+
add_subdirectory(src/arrow/gpu)
722+
endif()
723+
716724
set(ARROW_SRCS
717725
src/arrow/array.cc
718726
src/arrow/buffer.cc

cpp/src/arrow/builder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ class ARROW_EXPORT ArrayBuilder {
124124
std::shared_ptr<DataType> type() const { return type_; }
125125

126126
protected:
127+
ArrayBuilder() {}
128+
127129
std::shared_ptr<DataType> type_;
128130
MemoryPool* pool_;
129131

cpp/src/arrow/gpu/CMakeLists.txt

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
function(ADD_ARROW_CUDA_TEST REL_TEST_NAME)
19+
set(options)
20+
set(single_value_args)
21+
set(multi_value_args STATIC_LINK_LIBS)
22+
cmake_parse_arguments(ARG "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
23+
if(ARG_UNPARSED_ARGUMENTS)
24+
message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
25+
endif()
26+
27+
if(NO_TESTS OR NOT ARROW_BUILD_STATIC)
28+
return()
29+
endif()
30+
get_filename_component(TEST_NAME ${REL_TEST_NAME} NAME_WE)
31+
32+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${REL_TEST_NAME}.cc)
33+
# This test has a corresponding .cc file, set it up as an executable.
34+
set(TEST_PATH "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}")
35+
cuda_add_executable(${TEST_NAME} "${REL_TEST_NAME}.cc")
36+
37+
if (ARG_STATIC_LINK_LIBS)
38+
# Customize link libraries
39+
target_link_libraries(${TEST_NAME} ${ARG_STATIC_LINK_LIBS})
40+
else()
41+
target_link_libraries(${TEST_NAME} ${ARROW_TEST_LINK_LIBS})
42+
endif()
43+
add_dependencies(unittest ${TEST_NAME})
44+
else()
45+
# No executable, just invoke the test (probably a script) directly.
46+
set(TEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${REL_TEST_NAME})
47+
endif()
48+
49+
if (ARROW_TEST_MEMCHECK)
50+
SET_PROPERTY(TARGET ${TEST_NAME}
51+
APPEND_STRING PROPERTY
52+
COMPILE_FLAGS " -DARROW_VALGRIND")
53+
add_test(${TEST_NAME}
54+
bash -c "cd ${EXECUTABLE_OUTPUT_PATH}; valgrind --tool=memcheck --leak-check=full --leak-check-heuristics=stdstring --error-exitcode=1 ${TEST_PATH}")
55+
elseif(MSVC)
56+
add_test(${TEST_NAME} ${TEST_PATH})
57+
else()
58+
add_test(${TEST_NAME}
59+
${BUILD_SUPPORT_DIR}/run-test.sh ${CMAKE_BINARY_DIR} test ${TEST_PATH})
60+
endif()
61+
set_tests_properties(${TEST_NAME} PROPERTIES LABELS "unittest")
62+
endfunction()
63+
64+
#######################################
65+
# arrow_gpu
66+
#######################################
67+
68+
if (DEFINED ENV{CUDA_HOME})
69+
set(CUDA_TOOLKIT_ROOT_DIR "$ENV{CUDA_HOME}")
70+
endif()
71+
72+
find_package(CUDA REQUIRED)
73+
include_directories(SYSTEM ${CUDA_INCLUDE_DIRS})
74+
75+
set(ARROW_GPU_SRCS
76+
cuda_memory.cc
77+
)
78+
79+
set(ARROW_GPU_SHARED_LINK_LIBS
80+
arrow_shared
81+
)
82+
83+
cuda_add_library(arrow_gpu SHARED
84+
${ARROW_GPU_SRCS}
85+
)
86+
87+
install(FILES
88+
cuda_common.h
89+
cuda_memory.h
90+
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/arrow/gpu")
91+
92+
# pkg-config support
93+
configure_file(arrow-gpu.pc.in
94+
"${CMAKE_CURRENT_BINARY_DIR}/arrow-gpu.pc"
95+
@ONLY)
96+
install(
97+
FILES "${CMAKE_CURRENT_BINARY_DIR}/arrow-gpu.pc"
98+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/")
99+
100+
if (ARROW_BUILD_TESTS)
101+
set(ARROW_GPU_TEST_LINK_LIBS
102+
${ARROW_TEST_LINK_LIBS}
103+
arrow_gpu)
104+
ADD_ARROW_CUDA_TEST(cuda-test
105+
STATIC_LINK_LIBS ${ARROW_GPU_TEST_LINK_LIBS})
106+
endif()

cpp/src/arrow/gpu/arrow-gpu.pc.in

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
19+
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
20+
21+
Name: Apache Arrow GPU
22+
Description: GPU integration library for Apache Arrow
23+
Version: @ARROW_VERSION@
24+
Requires: arrow
25+
Libs: -L${libdir} -larrow_gpu
26+
Cflags: -I${includedir}

cpp/src/arrow/gpu/cuda-test.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include <cstdint>
19+
#include <limits>
20+
#include <string>
21+
22+
#include "gtest/gtest.h"
23+
24+
#include "arrow/status.h"
25+
#include "arrow/test-util.h"
26+
27+
#include "arrow/gpu/cuda_memory.h"
28+
29+
namespace arrow {
30+
namespace gpu {
31+
32+
class TestCudaBuffer : public ::testing::Test {};
33+
34+
TEST_F(TestCudaBuffer, Allocate) {
35+
const int device = 0;
36+
37+
const int64_t kSize = 100;
38+
std::shared_ptr<CudaBuffer> buffer;
39+
40+
ASSERT_OK(AllocateCudaBuffer(device, kSize, &buffer));
41+
ASSERT_EQ(kSize, buffer->size());
42+
}
43+
44+
} // namespace gpu
45+
} // namespace arrow

cpp/src/arrow/gpu/cuda_common.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
// Non-public header
19+
20+
#ifndef ARROW_GPU_CUDA_COMMON_H
21+
#define ARROW_GPU_CUDA_COMMON_H
22+
23+
#include <cuda_runtime_api.h>
24+
25+
namespace arrow {
26+
namespace gpu {
27+
28+
#define CUDA_DCHECK(STMT) \
29+
do { \
30+
int ret = (STMT); \
31+
DCHECK_EQ(0, ret); \
32+
(void)ret; \
33+
} while (0)
34+
35+
#define CUDA_RETURN_NOT_OK(STMT) \
36+
do { \
37+
cudaError_t ret = (STMT); \
38+
if (ret != cudaSuccess) { \
39+
return Status::IOError("Cuda API call failed: " #STMT); \
40+
} \
41+
} while (0)
42+
43+
} // namespace gpu
44+
} // namespace arrow
45+
46+
#endif // ARROW_GPU_CUDA_COMMON_H

cpp/src/arrow/gpu/cuda_memory.cc

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include "arrow/gpu/cuda_memory.h"
19+
20+
#include <cstdint>
21+
#include <memory>
22+
23+
#include "arrow/buffer.h"
24+
#include "arrow/status.h"
25+
#include "arrow/util/logging.h"
26+
27+
#include "arrow/gpu/cuda_common.h"
28+
29+
namespace arrow {
30+
namespace gpu {
31+
32+
CudaBuffer::~CudaBuffer() {
33+
if (own_data_) {
34+
CUDA_DCHECK(cudaFree(mutable_data_));
35+
}
36+
}
37+
38+
Status CudaBuffer::CopyHost(uint8_t* out) {
39+
CUDA_RETURN_NOT_OK(cudaMemcpy(out, data_, size_, cudaMemcpyDeviceToHost));
40+
return Status::OK();
41+
}
42+
43+
Status AllocateCudaBuffer(int gpu_number, const int64_t size,
44+
std::shared_ptr<CudaBuffer>* out) {
45+
CUDA_RETURN_NOT_OK(cudaSetDevice(gpu_number));
46+
uint8_t* data = nullptr;
47+
CUDA_RETURN_NOT_OK(
48+
cudaMalloc(reinterpret_cast<void**>(&data), static_cast<size_t>(size)));
49+
*out = std::make_shared<CudaBuffer>(data, size, gpu_number, true);
50+
return Status::OK();
51+
}
52+
53+
CudaHostBuffer::~CudaHostBuffer() { CUDA_DCHECK(cudaFreeHost(mutable_data_)); }
54+
55+
Status AllocateCudaHostBuffer(const int gpu_number, const int64_t size,
56+
std::shared_ptr<CudaHostBuffer>* out) {
57+
uint8_t* data = nullptr;
58+
CUDA_RETURN_NOT_OK(
59+
cudaMallocHost(reinterpret_cast<void**>(&data), static_cast<size_t>(size)));
60+
*out = std::make_shared<CudaHostBuffer>(data, size);
61+
return Status::OK();
62+
}
63+
64+
} // namespace gpu
65+
} // namespace arrow

0 commit comments

Comments
 (0)