Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
37 changes: 37 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 @@ -548,6 +566,25 @@ if(ARROW_CPU_FLAG STREQUAL "aarch64")
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")

Copy link
Copy Markdown
Author

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.

Added the missing blank line before if(ARROW_CPU_FLAG STREQUAL "riscv64"), as in the SVE/Arm block above.

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?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

GCC documentation (https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html) shows -mrvv-vector-bits only accepts scalable/zvl (and pairs with a zvlXXXb march extension), unlike SVE's direct -msve-vector-bits=N.
Fixing VLEN at compile time is also contrary to RVV's design: RVV is a variable-length architecture and the vector length is selected at runtime via vsetvl (xsimd's RVV backend is VLA as well). So the ARROW_HAVE_RVV${bits} macro is a runtime dispatch tag rather than a compile-time vector width.

@pitrou pitrou Oct 29, 2026 •

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.

Well, it looks like xsimd itself uses something like -march=rv64gcv_zvl${vector_bits} -mrvv-vector-bits=zvl.

I'm not sure how another approach would work. We need vectors to have a well-known length at compile-time.

else()
set(ARROW_HAVE_RVV_SIZELESS ON)
add_definitions(-DARROW_HAVE_RVV_SIZELESS)
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)
find_program(LD_MOLD ld.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