When loading model weights, FastFlowLM (FLM) calls mmap() followed by mlock() to pin host RAM, enabling the AMD NPU to perform direct DMA transfers without triggering page faults.
If the process exceeds its locked-memory resource limit (RLIMIT_MEMLOCK), mlock() fails with EAGAIN:
mmap(err=-11)For context, even a compact 1.2B parameter model requires ~1.6 GB of pinned memory. Systemd’s out-of-the-box DefaultLimitMEMLOCK is set to 8 MB (8388608 bytes), causing FLM model loading to fail immediately under default unit configurations.
Why /etc/security/limits.d Is Insufficient
A common, and recommended by FastFlowLM project, mitigation is dropping a memlock unlimited file into /etc/security/limits.d/. This is necessary for interactive user sessions, but insufficient for background processes and services.
limits.d configurations are enforced by pam_limits.so during PAM session initialization. Execution paths that bypass PAM will not inherit these limits:
| Execution Path | Uses PAM? | Enforced Limit Source |
|---|---|---|
| Interactive TTY / SSH login | Yes | /etc/security/limits.d/ |
systemd system service |
No | Unit LimitMEMLOCK (defaults to 8 MB) |
systemd --user unit |
No | User manager ceiling (defaults to 8 MB) |
| Non-PAM shells / processes | No | Parent process limit (defaults to 8 MB) |
Because systemctl --user and system services bypass PAM completely, FLM runtimes managed as systemd units inherit systemd’s default 8 MB limit regardless of /etc/security/limits.d/.
Additionally, a child user unit cannot exceed the resource ceiling set on its parent user@<UID>.service manager.
Resolution
To raise RLIMIT_MEMLOCK globally for systemd services and user-managed processes, apply two configuration drop-ins:
1. Set global systemd default
Create /etc/systemd/system.conf.d/10-memlock.conf:
[Manager]
DefaultLimitMEMLOCK=infinity2. Set user-manager ceiling override
Create /etc/systemd/system/user@.service.d/10-memlock.conf (applies to all user session managers):
[Service]
LimitMEMLOCK=infinity
If you only want this apply to a specific user you can set this only for the user. For instance, if your user id is 1000, you would use /etc/systemd/system/user@1000.service.d/10-memlock.conf.
3. Reload configuration
sudo systemctl daemon-reloadExisting services and user managers must be restarted (or the host rebooted) for the updated limit to take effect.
Verification
Verify the updated limits via systemd and the Linux kernel process interface:
Confirm global systemd default
systemctl show -p DefaultLimitMEMLOCKConfirm user manager limit
systemctl show user@$(id -u).service -p LimitMEMLOCKConfirm effective limit on the running FLM process
cat /proc/$(pgrep -f flm)/limits | grep 'Max locked'

