Skip to content

Commit a5dcb2a

Browse files
authored
Merge pull request #5909 from hmeiland/riscv64-blas-set-parameter
RISC-V: cache-aware GEMM blocking (get_L2_size + blas_set_parameter)
2 parents 873f005 + 269e1cd commit a5dcb2a

4 files changed

Lines changed: 74 additions & 7 deletions

File tree

common_macro.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2712,7 +2712,7 @@
27122712
#ifndef ASSEMBLER
27132713
#if !defined(DYNAMIC_ARCH) \
27142714
&& (defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) \
2715-
|| defined(ARCH_LOONGARCH64) || defined(ARCH_E2K) || defined(ARCH_ALPHA))
2715+
|| defined(ARCH_LOONGARCH64) || defined(ARCH_E2K) || defined(ARCH_ALPHA) || defined(ARCH_RISCV64))
27162716
extern BLASLONG gemm_offset_a;
27172717
extern BLASLONG gemm_offset_b;
27182718
extern BLASLONG bgemm_p;

driver/others/memory.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,7 @@ UNLOCK_COMMAND(&alloc_lock);
12201220
if (!blas_num_threads) blas_cpu_number = blas_get_cpu_number();
12211221
#endif
12221222

1223-
#if defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) || defined(ARCH_LOONGARCH64)
1223+
#if defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) || defined(ARCH_LOONGARCH64) || defined(ARCH_RISCV64)
12241224
#ifndef DYNAMIC_ARCH
12251225
blas_set_parameter();
12261226
#endif
@@ -2822,7 +2822,7 @@ void *blas_memory_alloc(int procpos){
28222822
if (!blas_num_threads) blas_cpu_number = blas_get_cpu_number();
28232823
#endif
28242824

2825-
#if defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) || defined(ARCH_LOONGARCH64)
2825+
#if defined(ARCH_X86) || defined(ARCH_X86_64) || defined(ARCH_IA64) || defined(ARCH_MIPS64) || defined(ARCH_ARM64) || defined(ARCH_LOONGARCH64) || defined(ARCH_RISCV64)
28262826
#ifndef DYNAMIC_ARCH
28272827
blas_set_parameter();
28282828
#endif

driver/others/parameter.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,3 +902,53 @@ void blas_set_parameter(void)
902902
}
903903

904904
#endif
905+
906+
#if defined(ARCH_RISCV64)
907+
908+
#include <stdio.h>
909+
910+
/* RISC-V has no architectural cache-size query (cf. x86 CPUID / LoongArch
911+
CPUCFG), so read the L2 (level 2, unified) size from Linux sysfs and fall
912+
back to 512 KB. Returns the L2 size in kilobytes. */
913+
int get_L2_size(void) {
914+
int size = 0;
915+
#if defined(OS_LINUX) || defined(OS_ANDROID)
916+
int idx;
917+
for (idx = 0; idx <= 4; idx++) {
918+
char path[80]; FILE *fp; int level = 0; long val = 0; char unit = 0;
919+
snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu0/cache/index%d/level", idx);
920+
fp = fopen(path, "r"); if (fp == NULL) continue;
921+
if (fscanf(fp, "%d", &level) != 1) { fclose(fp); continue; }
922+
fclose(fp); if (level != 2) continue;
923+
snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu0/cache/index%d/size", idx);
924+
fp = fopen(path, "r"); if (fp == NULL) continue;
925+
if (fscanf(fp, "%ld%c", &val, &unit) >= 1) {
926+
if (unit == 'M' || unit == 'm') val *= 1024;
927+
if (unit == 'G' || unit == 'g') val *= 1024 * 1024;
928+
size = (int)val;
929+
}
930+
fclose(fp); if (size > 0) break;
931+
}
932+
#endif
933+
if (size <= 0) size = 512;
934+
return size;
935+
}
936+
937+
void blas_set_parameter(void) {
938+
#if defined(SGEMM_DEFAULT_P_BASE)
939+
/* Scale each precision's packed-A dimension P from the detected L2, relative
940+
to the size the active core's base blocking targets (RISCV_L2_REFERENCE_KB).
941+
The bases come from the core's own param.h block, so this is not tied to any
942+
single core; Q and R keep their param.h defaults. */
943+
int l2 = get_L2_size(); /* KB */
944+
int scale = l2 / RISCV_L2_REFERENCE_KB;
945+
if (scale < 1) scale = 1;
946+
if (scale > 4) scale = 4;
947+
sgemm_p = SGEMM_DEFAULT_P_BASE * scale;
948+
dgemm_p = DGEMM_DEFAULT_P_BASE * scale;
949+
cgemm_p = CGEMM_DEFAULT_P_BASE * scale;
950+
zgemm_p = ZGEMM_DEFAULT_P_BASE * scale;
951+
#endif
952+
}
953+
954+
#endif

param.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3304,10 +3304,27 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33043304
#define SHGEMM_DEFAULT_P 128
33053305
#undef SBGEMM_DEFAULT_P
33063306
#define SBGEMM_DEFAULT_P 128
3307-
#define SGEMM_DEFAULT_P 128
3308-
#define DGEMM_DEFAULT_P 64
3309-
#define CGEMM_DEFAULT_P 64
3310-
#define ZGEMM_DEFAULT_P 64
3307+
/* Base packed-A (P) blocking for this core. On static builds blas_set_parameter()
3308+
scales P from the L2 cache detected at runtime, relative to RISCV_L2_REFERENCE_KB
3309+
(the L2 size these bases target); Q and R keep their param.h defaults. A cache
3310+
equal to the reference reproduces the stock blocking. DYNAMIC_ARCH uses the
3311+
literals directly (kernel/setparam-ref.c fills the gotoblas table from them). */
3312+
#define RISCV_L2_REFERENCE_KB 512
3313+
#define SGEMM_DEFAULT_P_BASE 128
3314+
#define DGEMM_DEFAULT_P_BASE 64
3315+
#define CGEMM_DEFAULT_P_BASE 64
3316+
#define ZGEMM_DEFAULT_P_BASE 64
3317+
#if defined(DYNAMIC_ARCH)
3318+
#define SGEMM_DEFAULT_P SGEMM_DEFAULT_P_BASE
3319+
#define DGEMM_DEFAULT_P DGEMM_DEFAULT_P_BASE
3320+
#define CGEMM_DEFAULT_P CGEMM_DEFAULT_P_BASE
3321+
#define ZGEMM_DEFAULT_P ZGEMM_DEFAULT_P_BASE
3322+
#else
3323+
#define SGEMM_DEFAULT_P sgemm_p
3324+
#define DGEMM_DEFAULT_P dgemm_p
3325+
#define CGEMM_DEFAULT_P cgemm_p
3326+
#define ZGEMM_DEFAULT_P zgemm_p
3327+
#endif
33113328

33123329
#undef SHGEMM_DEFAULT_Q
33133330
#define SHGEMM_DEFAULT_Q 128

0 commit comments

Comments
 (0)