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
2 changes: 2 additions & 0 deletions cpp/cmake_modules/DefineOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ takes precedence over ccache if a storage backend is configured" ON)
"SVE128" # fixed size SVE
"SVE256" # "
"SVE512" # "
"RVV"
"DEFAULT")

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

define_option(ARROW_ALTIVEC "Build with Altivec if compiler has support" ON)
Expand Down
21 changes: 21 additions & 0 deletions cpp/cmake_modules/SetupCxxFlags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ 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 "^(RVV|MAX)$")
set(ARROW_HAVE_RUNTIME_RVV ON)
add_definitions(-DARROW_HAVE_RUNTIME_RVV)
endif()
if(ARROW_SIMD_LEVEL STREQUAL "DEFAULT")
set(ARROW_SIMD_LEVEL "NONE")
endif()
endif()

# Support C11
Expand Down Expand Up @@ -552,6 +562,17 @@ 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")
if(ARROW_SIMD_LEVEL STREQUAL "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}")
add_definitions(-DARROW_HAVE_RVV)
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
19 changes: 19 additions & 0 deletions cpp/src/arrow/util/cpu_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#ifdef __linux__
# include <fstream>
# include <sys/auxv.h>
#endif

#ifdef __APPLE__
Expand Down Expand Up @@ -98,6 +99,24 @@ 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;

#if defined(__riscv) && __riscv_xlen == 64
# ifndef COMPAT_HWCAP_ISA_V
# define COMPAT_HWCAP_ISA_V (1UL << ('V' - 'A'))
# endif
bool rvv = false;
#ifdef __linux__
rvv = (getauxval(AT_HWCAP) & COMPAT_HWCAP_ISA_V) != 0;
#endif
*hardware_flags |= rvv ? CpuInfo::RVV : 0;
if (rvv) {
unsigned long vlenb = 0;
__asm__ volatile("csrr %0, vlenb" : "=r"(vlenb));
*hardware_flags |= (vlenb == 16) ? CpuInfo::RVV128 : 0;
*hardware_flags |= (vlenb == 32) ? CpuInfo::RVV256 : 0;
*hardware_flags |= (vlenb == 64) ? CpuInfo::RVV512 : 0;
}
#endif // __riscv && __riscv_xlen == 64

// 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
13 changes: 13 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,7 @@ enum class DispatchLevel : int {
SVE128,
SVE256,
SVE512,
RVV,
MAX
};

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

#if defined(ARROW_HAVE_RVV) || defined(ARROW_HAVE_RUNTIME_RVV)
# define ARROW_DISPATCH_TARGET_RVV(func) \
::arrow::internal::DynamicDispatchTarget{ \
::arrow::internal::DispatchLevel::RVV, \
(func), \
},
#else
# define ARROW_DISPATCH_TARGET_RVV(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 +363,8 @@ class DynamicDispatch {
return cpu_info->IsSupported(CpuInfo::SVE256);
case DispatchLevel::SVE512:
return cpu_info->IsSupported(CpuInfo::SVE512);
case DispatchLevel::RVV:
return cpu_info->IsSupported(CpuInfo::RVV);
default:
return false;
}
Expand Down
9 changes: 9 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,15 @@ 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
4 changes: 4 additions & 0 deletions cpp/src/arrow/util/simd.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
# include <arm_neon.h>
# endif

# if defined(ARROW_HAVE_RVV) || defined(ARROW_HAVE_RUNTIME_RVV)
# include <riscv_vector.h>
# endif

// GH-44098: Workaround for missing _mm256_set_m128i in older versions of GCC.
# if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
# define _mm256_set_m128i(hi, lo) \
Expand Down
Loading