git: 716c2def90b2 - main - misc/py-pytorch: fix unknown symbol on aarch64; add pkg-message
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 22 Sep 2026 01:55:45 UTC
The branch main has been updated by yuri:
URL: https://cgit.FreeBSD.org/ports/commit/?id=716c2def90b228eb75591f80cd787f16a2316c0f
commit 716c2def90b228eb75591f80cd787f16a2316c0f
Author: Yuri Victorovich <yuri@FreeBSD.org>
AuthorDate: 2026-09-21 23:58:07 +0000
Commit: Yuri Victorovich <yuri@FreeBSD.org>
CommitDate: 2026-09-22 01:55:42 +0000
misc/py-pytorch: fix unknown symbol on aarch64; add pkg-message
Add cpuinfo patch to support aarch64 for this.
---
misc/py-pytorch/Makefile | 8 +-
misc/py-pytorch/files/example.py | 4 +-
...tch-cpuinfo-with-freebsd-support_CMakeLists.txt | 19 +++
...nfo-with-freebsd-support_src_arm_freebsd_init.c | 186 +++++++++++++++++++++
...with-freebsd-support_src_cpuinfo_internal-api.h | 17 ++
.../patch-cpuinfo-with-freebsd-support_src_init.c | 19 +++
misc/py-pytorch/pkg-message | 26 +++
7 files changed, 275 insertions(+), 4 deletions(-)
diff --git a/misc/py-pytorch/Makefile b/misc/py-pytorch/Makefile
index 0b8689c7c067..d52876700a99 100644
--- a/misc/py-pytorch/Makefile
+++ b/misc/py-pytorch/Makefile
@@ -1,7 +1,7 @@
PORTNAME= pytorch
DISTVERSIONPREFIX= v
DISTVERSION= 2.14.0
-PORTREVISION= 1
+PORTREVISION= 2
CATEGORIES= misc # machine-learning
MASTER_SITES= https://github.com/pytorch/pytorch/releases/download/v${DISTVERSION}/
PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX}
@@ -104,6 +104,12 @@ CONFLICTS_BUILD= mpich # binaries are still linked with mpich when it is present
.include <bsd.port.options.mk>
+.if ${ARCH} == aarch64
+# torch's many dlopen'd shared libraries (OpenMP, mimalloc, cpuinfo, etc.) require
+# more initial-exec TLS than rtld's small default dlopen reserve, see rtld(1)
+TEST_ENV+= LD_STATIC_TLS_EXTRA=4096
+.endif
+
post-extract:
# upstream ships a stray *.orig file that 'make makepatch' would otherwise
# mistake for a patch baseline and turn into a bogus binary patch
diff --git a/misc/py-pytorch/files/example.py b/misc/py-pytorch/files/example.py
index 0c8046ca603e..739c0b228e1f 100644
--- a/misc/py-pytorch/files/example.py
+++ b/misc/py-pytorch/files/example.py
@@ -24,8 +24,6 @@ class DiscriminantNN(nn.Module):
nn.GELU(),
nn.Linear(128, 128),
nn.GELU(),
- nn.Linear(128, 128),
- nn.GELU(),
nn.Linear(128, 64),
nn.GELU(),
nn.Linear(64, 1)
@@ -51,7 +49,7 @@ scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0
print("Training started...")
epoch = 0
-max_epochs = 300000
+max_epochs = 10000
while epoch < max_epochs:
#print(f"Epoch {epoch:04d} | Learning Rate: {optimizer.param_groups[0]['lr']:.6f}")
diff --git a/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_CMakeLists.txt b/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_CMakeLists.txt
new file mode 100644
index 000000000000..ea7224de20d9
--- /dev/null
+++ b/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_CMakeLists.txt
@@ -0,0 +1,19 @@
+-- Build src/arm/freebsd/init.c for FreeBSD/aarch64 builds.
+-- cpuinfo has no FreeBSD backend for arm/aarch64 (only x86/freebsd exists),
+-- so cpuinfo_initialize() has no implementation to call into on aarch64 and
+-- libtorch_cpu.so fails to load with "Undefined symbol \"cpuinfo_isa\"".
+-- Paired with the new src/arm/freebsd/init.c added below.
+
+-- Upstreamed: https://github.com/pytorch/cpuinfo/pull/436
+
+--- cpuinfo-with-freebsd-support/CMakeLists.txt.orig 2026-09-21 07:02:31 UTC
++++ cpuinfo-with-freebsd-support/CMakeLists.txt
+@@ -211,6 +211,8 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
+ ENDIF()
+ ELSEIF(IS_APPLE_OS AND CPUINFO_TARGET_PROCESSOR MATCHES "arm64.*")
+ LIST(APPEND CPUINFO_SRCS src/arm/mach/init.c)
++ ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
++ LIST(APPEND CPUINFO_SRCS src/arm/freebsd/init.c)
+ ENDIF()
+ IF(CMAKE_SYSTEM_NAME STREQUAL "Android")
+ LIST(APPEND CPUINFO_SRCS
diff --git a/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_arm_freebsd_init.c b/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_arm_freebsd_init.c
new file mode 100644
index 000000000000..bf9ad0623901
--- /dev/null
+++ b/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_arm_freebsd_init.c
@@ -0,0 +1,186 @@
+-- New minimal FreeBSD/aarch64 backend for cpuinfo.
+-- cpuinfo upstream only ships a FreeBSD backend for x86 (src/x86/freebsd);
+-- aarch64 (this system's architecture) has no FreeBSD implementation, which
+-- leaves cpuinfo_initialize() unimplemented and cpuinfo_isa undefined,
+-- causing libtorch_cpu.so to fail to load with "Undefined symbol
+-- \"cpuinfo_isa\"" on FreeBSD/aarch64. Detects topology via the existing
+-- FreeBSD-only cpuinfo_freebsd_detect_topology() helper and ISA features via
+-- elf_aux_info(AT_HWCAP/AT_HWCAP2), whose bit layout FreeBSD keeps identical
+-- to Linux by design.
+
+-- Upstreamed: https://github.com/pytorch/cpuinfo/pull/436
+
+--- cpuinfo-with-freebsd-support/src/arm/freebsd/init.c.orig 2026-09-21 07:19:45 UTC
++++ cpuinfo-with-freebsd-support/src/arm/freebsd/init.c
+@@ -0,0 +1,171 @@
++/*
++ * Minimal AArch64/FreeBSD backend for cpuinfo.
++ *
++ * FreeBSD does not offer /proc/cpuinfo or the sysfs hwcap files that the
++ * Linux backend (src/arm/linux) relies on, so ISA feature bits are queried
++ * through elf_aux_info(AT_HWCAP/AT_HWCAP2), whose bit layout FreeBSD keeps
++ * identical to Linux by design (see sys/arm64/include/elf.h). Per-core
++ * microarchitecture identification (MIDR, vendor/uarch heuristics) and cache
++ * topology detection are not implemented; this only provides enough
++ * information (logical processor/core/package topology and ISA extensions)
++ * for callers such as ATen's cpuinfo-based capability queries.
++ */
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <sys/auxv.h>
++
++#include <cpuinfo.h>
++#include <cpuinfo/internal-api.h>
++#include <cpuinfo/log.h>
++#include <freebsd/api.h>
++
++#ifndef HWCAP_ASIMDHP
++#define HWCAP_ASIMDHP (1 << 10)
++#endif
++#ifndef HWCAP2_I8MM
++#define HWCAP2_I8MM (1 << 13)
++#endif
++#ifndef HWCAP2_BF16
++#define HWCAP2_BF16 (1 << 14)
++#endif
++#ifndef HWCAP2_SME
++#define HWCAP2_SME (1 << 23)
++#endif
++#ifndef HWCAP2_SVE2
++#define HWCAP2_SVE2 (1 << 1)
++#endif
++
++static uint64_t get_hwcap(int type) {
++ unsigned long value = 0;
++ if (elf_aux_info(type, &value, sizeof(value)) != 0) {
++ return 0;
++ }
++ return value;
++}
++
++struct cpuinfo_arm_isa cpuinfo_isa = {0};
++
++void cpuinfo_arm_freebsd_init(void) {
++ struct cpuinfo_processor* processors = NULL;
++ struct cpuinfo_core* cores = NULL;
++ struct cpuinfo_cluster* clusters = NULL;
++ struct cpuinfo_package* packages = NULL;
++ struct cpuinfo_uarch_info* uarchs = NULL;
++
++ struct cpuinfo_freebsd_topology freebsd_topology = cpuinfo_freebsd_detect_topology();
++ if (freebsd_topology.packages == 0) {
++ cpuinfo_log_error("failed to detect topology");
++ return;
++ }
++
++ processors = calloc(freebsd_topology.threads, sizeof(struct cpuinfo_processor));
++ cores = calloc(freebsd_topology.cores, sizeof(struct cpuinfo_core));
++ clusters = calloc(freebsd_topology.packages, sizeof(struct cpuinfo_cluster));
++ packages = calloc(freebsd_topology.packages, sizeof(struct cpuinfo_package));
++ uarchs = calloc(1, sizeof(struct cpuinfo_uarch_info));
++ if (processors == NULL || cores == NULL || clusters == NULL || packages == NULL || uarchs == NULL) {
++ cpuinfo_log_error("failed to allocate topology descriptors");
++ goto cleanup;
++ }
++
++ const uint32_t threads_per_package = freebsd_topology.threads / freebsd_topology.packages;
++ const uint32_t cores_per_package = freebsd_topology.cores / freebsd_topology.packages;
++ const uint32_t threads_per_core = freebsd_topology.threads_per_core;
++
++ uarchs[0] = (struct cpuinfo_uarch_info){
++ .uarch = cpuinfo_uarch_unknown,
++ .processor_count = freebsd_topology.threads,
++ .core_count = freebsd_topology.cores,
++ };
++
++ for (uint32_t i = 0; i < freebsd_topology.packages; i++) {
++ clusters[i] = (struct cpuinfo_cluster){
++ .processor_start = i * threads_per_package,
++ .processor_count = threads_per_package,
++ .core_start = i * cores_per_package,
++ .core_count = cores_per_package,
++ .cluster_id = 0,
++ .package = packages + i,
++ };
++ packages[i].processor_start = i * threads_per_package;
++ packages[i].processor_count = threads_per_package;
++ packages[i].core_start = i * cores_per_package;
++ packages[i].core_count = cores_per_package;
++ packages[i].cluster_start = i;
++ packages[i].cluster_count = 1;
++ strncpy(packages[i].name, "unknown", CPUINFO_PACKAGE_NAME_MAX - 1);
++ }
++ for (uint32_t i = 0; i < freebsd_topology.cores; i++) {
++ cores[i] = (struct cpuinfo_core){
++ .processor_start = i * threads_per_core,
++ .processor_count = threads_per_core,
++ .core_id = i % cores_per_package,
++ .cluster = clusters + i / cores_per_package,
++ .package = packages + i / cores_per_package,
++ };
++ }
++ for (uint32_t i = 0; i < freebsd_topology.threads; i++) {
++ processors[i].smt_id = i % threads_per_core;
++ processors[i].core = cores + i / threads_per_core;
++ processors[i].cluster = clusters + i / threads_per_package;
++ processors[i].package = packages + i / threads_per_package;
++ }
++
++ const uint64_t hwcap = get_hwcap(AT_HWCAP);
++ const uint64_t hwcap2 = get_hwcap(AT_HWCAP2);
++
++ struct cpuinfo_arm_isa isa;
++ memset(&isa, 0, sizeof(isa));
++ isa.aes = !!(hwcap & HWCAP_AES);
++ isa.pmull = !!(hwcap & HWCAP_PMULL);
++ isa.sha1 = !!(hwcap & HWCAP_SHA1);
++ isa.sha2 = !!(hwcap & HWCAP_SHA2);
++ isa.crc32 = !!(hwcap & HWCAP_CRC32);
++ isa.atomics = !!(hwcap & HWCAP_ATOMICS);
++ isa.rdm = !!(hwcap & HWCAP_ASIMDRDM);
++ isa.jscvt = !!(hwcap & HWCAP_JSCVT);
++ isa.fcma = !!(hwcap & HWCAP_FCMA);
++ isa.dot = !!(hwcap & HWCAP_ASIMDDP);
++ isa.fhm = !!(hwcap & HWCAP_ASIMDFHM);
++ isa.sve = !!(hwcap & HWCAP_SVE);
++ isa.fp16arith = !!(hwcap & HWCAP_FPHP) && !!(hwcap & HWCAP_ASIMDHP);
++ isa.i8mm = !!(hwcap2 & HWCAP2_I8MM);
++ isa.bf16 = !!(hwcap2 & HWCAP2_BF16);
++ isa.sve2 = !!(hwcap2 & HWCAP2_SVE2);
++ isa.sme = !!(hwcap2 & HWCAP2_SME);
++
++ /* Commit changes */
++ cpuinfo_isa = isa;
++ cpuinfo_processors = processors;
++ cpuinfo_cores = cores;
++ cpuinfo_clusters = clusters;
++ cpuinfo_packages = packages;
++
++ cpuinfo_processors_count = freebsd_topology.threads;
++ cpuinfo_cores_count = freebsd_topology.cores;
++ cpuinfo_clusters_count = freebsd_topology.packages;
++ cpuinfo_packages_count = freebsd_topology.packages;
++
++ cpuinfo_uarchs = uarchs;
++ cpuinfo_uarchs_count = 1;
++
++ __sync_synchronize();
++
++ cpuinfo_is_initialized = true;
++
++ processors = NULL;
++ cores = NULL;
++ clusters = NULL;
++ packages = NULL;
++ uarchs = NULL;
++
++cleanup:
++ free(processors);
++ free(cores);
++ free(clusters);
++ free(packages);
++ free(uarchs);
++}
diff --git a/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_cpuinfo_internal-api.h b/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_cpuinfo_internal-api.h
new file mode 100644
index 000000000000..76e517f2742c
--- /dev/null
+++ b/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_cpuinfo_internal-api.h
@@ -0,0 +1,17 @@
+-- Declare cpuinfo_arm_freebsd_init(), the new FreeBSD/aarch64 backend entry
+-- point, alongside the other per-OS/arch init functions.
+-- Needed so src/init.c can dispatch to it on FreeBSD/aarch64; see
+-- src/arm/freebsd/init.c for why this backend is required.
+
+-- Upstreamed: https://github.com/pytorch/cpuinfo/pull/436
+
+--- cpuinfo-with-freebsd-support/src/cpuinfo/internal-api.h.orig 2026-09-21 07:02:31 UTC
++++ cpuinfo-with-freebsd-support/src/cpuinfo/internal-api.h
+@@ -59,6 +59,7 @@ CPUINFO_PRIVATE void cpuinfo_arm_linux_init(void);
+ #endif
+ CPUINFO_PRIVATE void cpuinfo_arm_mach_init(void);
+ CPUINFO_PRIVATE void cpuinfo_arm_linux_init(void);
++CPUINFO_PRIVATE void cpuinfo_arm_freebsd_init(void);
+ CPUINFO_PRIVATE void cpuinfo_riscv_linux_init(void);
+ CPUINFO_PRIVATE void cpuinfo_emscripten_init(void);
+
diff --git a/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_init.c b/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_init.c
new file mode 100644
index 000000000000..83d72d79269e
--- /dev/null
+++ b/misc/py-pytorch/files/patch-cpuinfo-with-freebsd-support_src_init.c
@@ -0,0 +1,19 @@
+-- Dispatch cpuinfo_initialize() to the new cpuinfo_arm_freebsd_init() on
+-- FreeBSD/aarch64, mirroring the existing __FreeBSD__ dispatch already
+-- present for x86. Without this, cpuinfo_initialize() silently does nothing
+-- on FreeBSD/aarch64 and libtorch_cpu.so fails to load with "Undefined
+-- symbol \"cpuinfo_isa\"".
+
+-- Upstreamed: https://github.com/pytorch/cpuinfo/pull/436
+
+--- cpuinfo-with-freebsd-support/src/init.c.orig 2026-09-21 07:02:31 UTC
++++ cpuinfo-with-freebsd-support/src/init.c
+@@ -38,6 +38,8 @@ bool CPUINFO_ABI cpuinfo_initialize(void) {
+ pthread_once(&init_guard, &cpuinfo_arm_linux_init);
+ #elif defined(__MACH__) && defined(__APPLE__)
+ pthread_once(&init_guard, &cpuinfo_arm_mach_init);
++#elif defined(__FreeBSD__)
++ pthread_once(&init_guard, &cpuinfo_arm_freebsd_init);
+ #elif defined(_WIN32)
+ InitOnceExecuteOnce(&init_guard, &cpuinfo_arm_windows_init, NULL, NULL);
+ #else
diff --git a/misc/py-pytorch/pkg-message b/misc/py-pytorch/pkg-message
new file mode 100644
index 000000000000..a45d4f96b31e
--- /dev/null
+++ b/misc/py-pytorch/pkg-message
@@ -0,0 +1,26 @@
+[
+{ type: install
+ message: <<EOM
+You installed PyTorch: an AI toolkit.
+
+## Need env var on amd64 Zen5/Zen6 CPU architectures
+
+Due to the bug in the OpenBLAS CPU arch detection PyTorch will
+crash on Zen5/Zen6 CPU architectures.
+
+Reference: https://github.com/OpenMathLib/OpenBLAS/issues/6029
+
+Use the following environment variable to work around this problem:
+OPENBLAS_CORETYPE=SKYLAKEX (some other values might work too)
+
+The same problem exists in all software that uses OpenBLAS, not just PyTorch.
+
+## Need env var on aarch64 due to high TLS requirements
+
+When running PyTorch on aarch64 you likely need to have this environment
+variable set:
+LD_STATIC_TLS_EXTRA=4096
+
+EOM
+}
+]