Skip to content

Commit

Permalink
Add defensive try/catch around setting processor affinity (for AMD sy…
Browse files Browse the repository at this point in the history
…stems which threw an Exception). Add dump-processor command to UCI.
  • Loading branch information
dje-dev committed Jan 3, 2021
1 parent 19cebb0 commit 2f09a83
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 17 deletions.
57 changes: 40 additions & 17 deletions src/Ceres.Base/OperatingSystem/HardwareManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,29 +68,52 @@ public static void VerifyHardwareSoftwareCompatability()

static bool haveAffinitizedSingle = false;


/// <summary>
/// Write diagnostic information to console relating to processor configuration.
/// </summary>
public static void DumpProcessorInfo()
{
Console.WriteLine("NumCPUSockets: " + WindowsHardware.NumCPUSockets);
Console.WriteLine("NumProcessors: " + System.Environment.ProcessorCount);
Console.WriteLine("Affinity Mask: " + Process.GetCurrentProcess().ProcessorAffinity);
}

private static void AffinitizeSingleProcessor()
{
// NOTE: Someday it would be desirable to allow different
// logical calculations (e.g. chess tree searches)
// to be placed on distinct sockets, and not restrict
// all computation to a single socket.
// But then we'd have to abandon use of TPL and .NET thread pool
// completely and use our own versions which were processor constrained.
bool isMultisocket = WindowsHardware.NumCPUSockets > 1;
if (isMultisocket)
try
{
// This dramatically improves performance (multithreading)
Process Proc = Process.GetCurrentProcess();
long AffinityMask = (long)Proc.ProcessorAffinity;
// TODO: need to calculate correct mask. Currently below we only take half the bits (processors)
var mask = (1 << (System.Environment.ProcessorCount / 2)) - 1;
AffinityMask &= mask;
Proc.ProcessorAffinity = (IntPtr)AffinityMask;

haveAffinitizedSingle = true;
// NOTE: Someday it would be desirable to allow different
// logical calculations (e.g. chess tree searches)
// to be placed on distinct sockets, and not restrict
// all computation to a single socket.
// But then we'd have to abandon use of TPL and .NET thread pool
// completely and use our own versions which were processor constrained.
bool isMultisocket = WindowsHardware.NumCPUSockets > 1;
if (isMultisocket)
{
// This dramatically improves performance (multithreading)
Process Proc = Process.GetCurrentProcess();
long AffinityMask = (long)Proc.ProcessorAffinity;
// TODO: need to calculate correct mask. Currently below we only take half the bits (processors)
var mask = (1 << (System.Environment.ProcessorCount / 2)) - 1;
AffinityMask &= mask;
Proc.ProcessorAffinity = (IntPtr)AffinityMask;

haveAffinitizedSingle = true;
}
}
catch (Exception exc)
{
// Some AMD systems fail when setting affinity mask
// Therefore recover gracefully
// TODO: resolve this on AMD systems
Console.WriteLine("Note: failure in call to AffinitizeSingleProcessor.");
}

}


}
}

5 changes: 5 additions & 0 deletions src/Ceres.Features/UCI/UCIManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
using System.Collections.Generic;
using Ceres.MCTS.Params;
using Ceres.MCTS.MTCSNodes.Storage;
using Ceres.Base.OperatingSystem;

#endregion

Expand Down Expand Up @@ -259,6 +260,10 @@ public void PlayUCI()
Console.WriteLine("info string No search manager created");
break;

case "dump-processor":
HardwareManager.DumpProcessorInfo();
break;

case "dump-time":
if (curManager != null)
curManager.DumpTimeInfo();
Expand Down

0 comments on commit 2f09a83

Please sign in to comment.