Hi,
I am using the latest version of Ampl CE with the C# API.
I need to launch parallel solves of independant problems. Since it did not work, I coded a simple example to illustrate :
public void TestAmplParallel()
{
int nbTest = 20;
Stopwatch timer = new Stopwatch();
object locker = new object();
Console.WriteLine("Start parallel test...");
timer.Restart();
Parallel.For(0, nbTest, i =>
{
lock (locker)
{
File.Copy("Modele.mod", $"Modele_{i}.mod", true);
File.Copy("Modele.dat", $"Modele_{i}.dat", true);
}
var ampl = new AMPL();
ampl.EnableOutputRouting();
ampl.Read($"Modele_{i}.mod");
ampl.ReadData($"Modele_{i}.dat");
ampl.Solve("", "cbc");
var objValue = ampl.GetObjective("obj").Value;
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} : obj = {objValue}");
});
Console.WriteLine($"Duration : {timer.Elapsed.TotalSeconds} seconds");
Console.ReadKey();
}
The first optimizations succeed but it freezes at some times. Using debugger, it shows that we are stuck at “var ampl = new AMPL();” for the remaining threads.
I suspected an issue from the licence system since amplkey.log indicated messages like :
2025/01/13 22:34:59 Cannot unlock “D:\Dev/amplkey.lock”, reason: remove D:\Dev/amplkey.lock: The process cannot access the file because it is being used by another process.
So I tried another version calling directly the executable without api calls :
public void TestAmplParallel2()
{
int nbTest = 20;
Stopwatch timer = new Stopwatch();
object locker = new object();
Console.WriteLine("Start parallel test...");
timer.Restart();
Parallel.For(0, nbTest, i =>
{
lock (locker)
{
File.Copy("Modele.mod", $"Modele_{i}.mod", true);
File.Copy("Modele.dat", $"Modele_{i}.dat", true);
}
StringWriter sw = new StringWriter();
sw.WriteLine($"model 'Modele_{i}.mod';");
sw.WriteLine($"data 'Modele_{i}.dat';");
sw.WriteLine($"option solver cbc;");
sw.WriteLine($"solve;");
sw.WriteLine($"print _obj[1] > 'Modele_{i}.sol';");
File.WriteAllText($"Modele_{i}.run", sw.ToString(), Encoding.GetEncoding(1252));
string arguments = string.Format(@"""{0}""", $"Modele_{i}.run");
var process = new Process();
process.StartInfo.FileName = "ampl.exe";
process.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
process.StartInfo.Arguments = arguments;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.WaitForExit();
var objValue = File.ReadAllText($"Modele_{i}.sol");
Console.Write($"Thread {Thread.CurrentThread.ManagedThreadId} : obj = {objValue}");
});
Console.WriteLine($"Duration : {timer.Elapsed.TotalSeconds} seconds");
Console.ReadKey();
}
It works perfectly (even when incresaing the number of tests). I conclude that the problem is not coming from the licence manager but from the api.
Any help would be very appreciate
Modele.dat (199 Bytes)
Modele.mod (304 Bytes)