microsoft/FASTER · error · FasterException

Unable to affinitize thread

Error message

Unable to affinitize thread

What it means

FasterException thrown by Native32.AffinitizeThreadRoundRobin when the Win32 SetThreadGroupAffinity call returns 0 (failure). The library uses this during epoch/thread affinitization to pin threads across processor groups; if the OS refuses the affinity mask, the setup fails fast.

Solutions

  1. Run on hardware/VM where the thread count does not exceed available logical processors per group
  2. Avoid thread affinitization (do not enable affinity options) in containers or restricted environments
  3. Verify the process has permission to set thread affinity (not restricted by Job Object policies)
  4. Confirm processor group layout with GetActiveProcessorGroupCount/GetActiveProcessorCount and align threadIdx

Example fix

// before
for (int i = 0; i < 128; i++)
    Native32.AffinitizeThreadRoundRobin((uint)i, threadHandles[i]);
// after
int procs = Environment.ProcessorCount;
for (int i = 0; i < Math.Min(128, procs); i++)
    Native32.AffinitizeThreadRoundRobin((uint)i, threadHandles[i]);
Defensive patterns

Strategy: try-catch

Validate before calling

if (OperatingSystem.IsWindows() && threadIdx < Environment.ProcessorCount && CanSetThreadAffinity()) { ... }

Try / catch

try { Native32.AffinitizeThreadRoundRobin(idx, thread); }
catch (FasterException ex) when (ex.Message == "Unable to affinitize thread")
{ logger.Warn("Affinity not permitted; continuing without pinning"); }

Prevention

When it happens

Trigger: Calling AffinitizeThreadRoundRobin (used by FasterLog/FASTER server or TickAffinitize setup) on Windows when the requested threadIdx maps to a group/mask the OS rejects — e.g. mask 1 << (threadIdx % procsPerGroup) exceeding available processors in the group, or insufficient privileges (restricted job objects, containers, VMs with limited CPU groups).

Common situations: Running in Windows containers or constrained VMs where thread affinity is not permitted; launching more threads than logical processors; running on systems with multiple processor groups where group math mismatches; using non-Windows where this P/Invoke path is unsupported.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15). Data as JSON: /api/errors/f48b120e9198b0ec. Report an issue: GitHub.

Appendix: source

Thrown at cs/src/core/Utilities/Native32.cs:238

        {
            uint nrOfProcessors = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
            ushort nrOfProcessorGroups = GetActiveProcessorGroupCount();
            uint nrOfProcsPerGroup = nrOfProcessors / nrOfProcessorGroups;

            GROUP_AFFINITY groupAffinityThread = default(GROUP_AFFINITY);
            GROUP_AFFINITY oldAffinityThread = default(GROUP_AFFINITY);

            IntPtr thread = GetCurrentThread();
            GetThreadGroupAffinity(thread, ref groupAffinityThread);

            threadIdx = threadIdx % nrOfProcessors;

            groupAffinityThread.Mask = (ulong)1L << ((int)(threadIdx % (int)nrOfProcsPerGroup));
            groupAffinityThread.Group = (uint)(threadIdx / nrOfProcsPerGroup);

            if (SetThreadGroupAffinity(thread, ref groupAffinityThread, ref oldAffinityThread) == 0)
            {
                throw new FasterException("Unable to affinitize thread");
            }
        }

        /// <summary>
        /// Get number of groups (sockets) and processors per group
        /// </summary>
        /// <returns></returns>
        public static (uint numGroups, uint numProcsPerGroup) GetNumGroupsProcsPerGroup()
        {
            uint nrOfProcessors = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
            ushort nrOfProcessorGroups = GetActiveProcessorGroupCount();
            uint nrOfProcsPerGroup = nrOfProcessors / nrOfProcessorGroups;
            return (nrOfProcessorGroups, nrOfProcsPerGroup);
        }

        /// <summary>
        /// Accepts thread id = 0, 1, 2, ... and sprays them round-robin
        /// across all cores (viewed as a flat space). On NUMA machines,

View on GitHub (pinned to 321d872eab)