Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ python/doc/

.vscode
.idea/
.icodemate/
.pytest_cache/
pkgs
docker_cache
Expand Down
7 changes: 7 additions & 0 deletions cpp/cmake_modules/DefineOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ takes precedence over ccache if a storage backend is configured" ON)
"SVE128" # fixed size SVE
"SVE256" # "
"SVE512" # "
"RVV" # size agnostic RVV
"RVV128" # fixed size RVV
"RVV256" # "
"RVV512" # "
"DEFAULT")

define_option_string(ARROW_RUNTIME_SIMD_LEVEL
Expand All @@ -183,6 +187,9 @@ takes precedence over ccache if a storage backend is configured" ON)
"SVE128" # fixed size SVE
"SVE256" # "
"SVE512" # "
"RVV128" # fixed size RVV
"RVV256" # "
"RVV512" # "
"MAX")

define_option(ARROW_ALTIVEC "Build with Altivec if compiler has support" ON)
Expand Down
36 changes: 36 additions & 0 deletions cpp/cmake_modules/SetupCxxFlags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,24 @@ elseif(ARROW_CPU_FLAG STREQUAL "aarch64")
if(ARROW_SIMD_LEVEL STREQUAL "DEFAULT")
set(ARROW_SIMD_LEVEL "NEON")
endif()
elseif(ARROW_CPU_FLAG STREQUAL "riscv64")
set(ARROW_RVV_MARCH "rv64gcv")
check_cxx_compiler_flag("-march=${ARROW_RVV_MARCH}" CXX_SUPPORTS_RVV)
if(CXX_SUPPORTS_RVV AND ARROW_RUNTIME_SIMD_LEVEL MATCHES "^(RVV128|RVV256|RVV512|MAX)$")
set(ARROW_HAVE_RUNTIME_RVV128 ON)
add_definitions(-DARROW_HAVE_RUNTIME_RVV128)
endif()
if(CXX_SUPPORTS_RVV AND ARROW_RUNTIME_SIMD_LEVEL MATCHES "^(RVV256|RVV512|MAX)$")
set(ARROW_HAVE_RUNTIME_RVV256 ON)
add_definitions(-DARROW_HAVE_RUNTIME_RVV256)
endif()
if(CXX_SUPPORTS_RVV AND ARROW_RUNTIME_SIMD_LEVEL MATCHES "^(RVV512|MAX)$")
set(ARROW_HAVE_RUNTIME_RVV512 ON)
add_definitions(-DARROW_HAVE_RUNTIME_RVV512)
endif()
if(ARROW_SIMD_LEVEL STREQUAL "DEFAULT")
set(ARROW_SIMD_LEVEL "NONE")
endif()
endif()

# Support C11
Expand Down Expand Up @@ -547,6 +565,24 @@ if(ARROW_CPU_FLAG STREQUAL "aarch64")
message(WARNING "ARROW_SIMD_LEVEL=${ARROW_SIMD_LEVEL} not supported by Arm.")
endif()
endif()
if(ARROW_CPU_FLAG STREQUAL "riscv64")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: add line break as above.

Suggested change
if(ARROW_CPU_FLAG STREQUAL "riscv64")
if(ARROW_CPU_FLAG STREQUAL "riscv64")

if(ARROW_SIMD_LEVEL MATCHES "RVV")
if(NOT CXX_SUPPORTS_RVV)
message(FATAL_ERROR "RVV required but compiler doesn't support it.")
endif()
set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -march=${ARROW_RVV_MARCH}")
string(REGEX MATCH "[0-9]+" RVV_VECTOR_BITS ${ARROW_SIMD_LEVEL})
if(RVV_VECTOR_BITS)
set(ARROW_HAVE_RVV${RVV_VECTOR_BITS} ON)
add_definitions(-DARROW_HAVE_RVV${RVV_VECTOR_BITS})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we also enable a compiler option for the given vector size, as in SVE above?

else()
set(ARROW_HAVE_RVV ON)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps call it ARROW_HAVE_RVV_SIZELESS just like SVE above?

add_definitions(-DARROW_HAVE_RVV)
endif()
elseif(NOT ARROW_SIMD_LEVEL STREQUAL "NONE")
message(WARNING "ARROW_SIMD_LEVEL=${ARROW_SIMD_LEVEL} not supported by riscv64.")
endif()
endif()

if(NOT WIN32 AND NOT APPLE)
if(ARROW_USE_MOLD)
Expand Down
8 changes: 8 additions & 0 deletions cpp/src/arrow/util/cpu_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ void OsRetrieveCpuInfo(int64_t* hardware_flags, CpuInfo::Vendor* vendor) {
*hardware_flags |= (sve && sve_size == 32) ? CpuInfo::SVE256 : 0;
*hardware_flags |= (sve && sve_size == 64) ? CpuInfo::SVE512 : 0;

// RVV and length
const bool rvv = cpu.rvv();
const auto rvv_size = cpu.rvv_size_bytes();
*hardware_flags |= rvv ? CpuInfo::RVV : 0;
*hardware_flags |= (rvv && rvv_size == 16) ? CpuInfo::RVV128 : 0;
*hardware_flags |= (rvv && rvv_size == 32) ? CpuInfo::RVV256 : 0;
*hardware_flags |= (rvv && rvv_size == 64) ? CpuInfo::RVV512 : 0;

// x86 only
switch (cpu.known_manufacturer()) {
case (xsimd::x86_manufacturer::intel):
Expand Down
6 changes: 6 additions & 0 deletions cpp/src/arrow/util/cpu_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ class ARROW_EXPORT CpuInfo {
static constexpr int64_t SVE256 = (1LL << 34);
static constexpr int64_t SVE512 = (1LL << 35);

/// RISC-V features
static constexpr int64_t RVV = (1LL << 37);
static constexpr int64_t RVV128 = (1LL << 38);
static constexpr int64_t RVV256 = (1LL << 39);
static constexpr int64_t RVV512 = (1LL << 40);

/// Cache enums for L1 (data), L2 and L3
enum class CacheLevel { L1 = 0, L2, L3, Last = L3 };

Expand Down
39 changes: 39 additions & 0 deletions cpp/src/arrow/util/dispatch_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ enum class DispatchLevel : int {
SVE128,
SVE256,
SVE512,
RVV128,
RVV256,
RVV512,
MAX
};

Expand Down Expand Up @@ -221,6 +224,36 @@ constexpr DynamicDispatchTarget<Func> BestDispatchTarget(
# define ARROW_DISPATCH_TARGET_SVE512(func)
#endif

#if defined(ARROW_HAVE_RVV128) || defined(ARROW_HAVE_RUNTIME_RVV128)
# define ARROW_DISPATCH_TARGET_RVV128(func) \
::arrow::internal::DynamicDispatchTarget{ \
::arrow::internal::DispatchLevel::RVV128, \
(func), \
},
#else
# define ARROW_DISPATCH_TARGET_RVV128(func)
#endif

#if defined(ARROW_HAVE_RVV256) || defined(ARROW_HAVE_RUNTIME_RVV256)
# define ARROW_DISPATCH_TARGET_RVV256(func) \
::arrow::internal::DynamicDispatchTarget{ \
::arrow::internal::DispatchLevel::RVV256, \
(func), \
},
#else
# define ARROW_DISPATCH_TARGET_RVV256(func)
#endif

#if defined(ARROW_HAVE_RVV512) || defined(ARROW_HAVE_RUNTIME_RVV512)
# define ARROW_DISPATCH_TARGET_RVV512(func) \
::arrow::internal::DynamicDispatchTarget{ \
::arrow::internal::DispatchLevel::RVV512, \
(func), \
},
#else
# define ARROW_DISPATCH_TARGET_RVV512(func)
#endif

/// A concept to specify how dynamic dispatch should be handled.
///
/// A requirement is that the list of available targets must be compile time
Expand Down Expand Up @@ -352,6 +385,12 @@ class DynamicDispatch {
return cpu_info->IsSupported(CpuInfo::SVE256);
case DispatchLevel::SVE512:
return cpu_info->IsSupported(CpuInfo::SVE512);
case DispatchLevel::RVV128:
return cpu_info->IsSupported(CpuInfo::RVV128);
case DispatchLevel::RVV256:
return cpu_info->IsSupported(CpuInfo::RVV256);
case DispatchLevel::RVV512:
return cpu_info->IsSupported(CpuInfo::RVV512);
default:
return false;
}
Expand Down
8 changes: 8 additions & 0 deletions cpp/src/arrow/util/io_util_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,14 @@ TEST(CpuInfo, Basic) {
ASSERT_EQ(ci->hardware_flags(), 0);
ci_rw->EnableFeature(original_hardware_flags, true);
ASSERT_EQ(ci->hardware_flags(), original_hardware_flags);

#if defined(__riscv) && __riscv_xlen == 64
if (ci->IsDetected(CpuInfo::RVV)) {
EXPECT_NE(ci->hardware_flags() & CpuInfo::RVV, 0);
EXPECT_NE(
ci->hardware_flags() & (CpuInfo::RVV128 | CpuInfo::RVV256 | CpuInfo::RVV512), 0);
}
#endif
}

TEST(Memory, TotalMemory) {
Expand Down
Loading