diff --git a/common_macro.h b/common_macro.h index 4051cb3794..ea2cf5ea15 100644 --- a/common_macro.h +++ b/common_macro.h @@ -2712,7 +2712,7 @@ #ifndef ASSEMBLER #if !defined(DYNAMIC_ARCH) \ && (defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) \ - || defined(ARCH_LOONGARCH64) || defined(ARCH_E2K) || defined(ARCH_ALPHA)) + || defined(ARCH_LOONGARCH64) || defined(ARCH_E2K) || defined(ARCH_ALPHA) || defined(ARCH_RISCV64)) extern BLASLONG gemm_offset_a; extern BLASLONG gemm_offset_b; extern BLASLONG bgemm_p; diff --git a/driver/others/memory.c b/driver/others/memory.c index d7df981e66..e25dfbae6e 100644 --- a/driver/others/memory.c +++ b/driver/others/memory.c @@ -1220,7 +1220,7 @@ UNLOCK_COMMAND(&alloc_lock); if (!blas_num_threads) blas_cpu_number = blas_get_cpu_number(); #endif -#if defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) || defined(ARCH_LOONGARCH64) +#if defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) || defined(ARCH_LOONGARCH64) || defined(ARCH_RISCV64) #ifndef DYNAMIC_ARCH blas_set_parameter(); #endif @@ -2822,7 +2822,7 @@ void *blas_memory_alloc(int procpos){ if (!blas_num_threads) blas_cpu_number = blas_get_cpu_number(); #endif -#if defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) || defined(ARCH_LOONGARCH64) +#if defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) || defined(ARCH_LOONGARCH64) || defined(ARCH_RISCV64) #ifndef DYNAMIC_ARCH blas_set_parameter(); #endif diff --git a/driver/others/parameter.c b/driver/others/parameter.c index 3a1363e0ea..e1451fc714 100644 --- a/driver/others/parameter.c +++ b/driver/others/parameter.c @@ -902,3 +902,53 @@ void blas_set_parameter(void) } #endif + +#if defined(ARCH_RISCV64) + +#include + +/* RISC-V has no architectural cache-size query (cf. x86 CPUID / LoongArch + CPUCFG), so read the L2 (level 2, unified) size from Linux sysfs and fall + back to 512 KB. Returns the L2 size in kilobytes. */ +int get_L2_size(void) { + int size = 0; +#if defined(OS_LINUX) || defined(OS_ANDROID) + int idx; + for (idx = 0; idx <= 4; idx++) { + char path[80]; FILE *fp; int level = 0; long val = 0; char unit = 0; + snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu0/cache/index%d/level", idx); + fp = fopen(path, "r"); if (fp == NULL) continue; + if (fscanf(fp, "%d", &level) != 1) { fclose(fp); continue; } + fclose(fp); if (level != 2) continue; + snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu0/cache/index%d/size", idx); + fp = fopen(path, "r"); if (fp == NULL) continue; + if (fscanf(fp, "%ld%c", &val, &unit) >= 1) { + if (unit == 'M' || unit == 'm') val *= 1024; + if (unit == 'G' || unit == 'g') val *= 1024 * 1024; + size = (int)val; + } + fclose(fp); if (size > 0) break; + } +#endif + if (size <= 0) size = 512; + return size; +} + +void blas_set_parameter(void) { +#if defined(SGEMM_DEFAULT_P_BASE) + /* Scale each precision's packed-A dimension P from the detected L2, relative + to the size the active core's base blocking targets (RISCV_L2_REFERENCE_KB). + The bases come from the core's own param.h block, so this is not tied to any + single core; Q and R keep their param.h defaults. */ + int l2 = get_L2_size(); /* KB */ + int scale = l2 / RISCV_L2_REFERENCE_KB; + if (scale < 1) scale = 1; + if (scale > 4) scale = 4; + sgemm_p = SGEMM_DEFAULT_P_BASE * scale; + dgemm_p = DGEMM_DEFAULT_P_BASE * scale; + cgemm_p = CGEMM_DEFAULT_P_BASE * scale; + zgemm_p = ZGEMM_DEFAULT_P_BASE * scale; +#endif +} + +#endif diff --git a/param.h b/param.h index 9389c4135f..4a9e0a4b08 100644 --- a/param.h +++ b/param.h @@ -3265,10 +3265,27 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define SHGEMM_DEFAULT_P 128 #undef SBGEMM_DEFAULT_P #define SBGEMM_DEFAULT_P 128 -#define SGEMM_DEFAULT_P 128 -#define DGEMM_DEFAULT_P 64 -#define CGEMM_DEFAULT_P 64 -#define ZGEMM_DEFAULT_P 64 +/* Base packed-A (P) blocking for this core. On static builds blas_set_parameter() + scales P from the L2 cache detected at runtime, relative to RISCV_L2_REFERENCE_KB + (the L2 size these bases target); Q and R keep their param.h defaults. A cache + equal to the reference reproduces the stock blocking. DYNAMIC_ARCH uses the + literals directly (kernel/setparam-ref.c fills the gotoblas table from them). */ +#define RISCV_L2_REFERENCE_KB 512 +#define SGEMM_DEFAULT_P_BASE 128 +#define DGEMM_DEFAULT_P_BASE 64 +#define CGEMM_DEFAULT_P_BASE 64 +#define ZGEMM_DEFAULT_P_BASE 64 +#if defined(DYNAMIC_ARCH) +#define SGEMM_DEFAULT_P SGEMM_DEFAULT_P_BASE +#define DGEMM_DEFAULT_P DGEMM_DEFAULT_P_BASE +#define CGEMM_DEFAULT_P CGEMM_DEFAULT_P_BASE +#define ZGEMM_DEFAULT_P ZGEMM_DEFAULT_P_BASE +#else +#define SGEMM_DEFAULT_P sgemm_p +#define DGEMM_DEFAULT_P dgemm_p +#define CGEMM_DEFAULT_P cgemm_p +#define ZGEMM_DEFAULT_P zgemm_p +#endif #undef SHGEMM_DEFAULT_Q #define SHGEMM_DEFAULT_Q 128