Merge pull request #5909 from hmeiland/riscv64-blas-set-parameter
RISC-V: cache-aware GEMM blocking (get_L2_size + blas_set_parameter)
This commit is contained in:
+1
-1
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -902,3 +902,53 @@ void blas_set_parameter(void)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_RISCV64)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -3304,10 +3304,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
|
||||
|
||||
Reference in New Issue
Block a user