Compare commits

...

7 Commits

Author SHA1 Message Date
Jared Broad
4151c40b39 Shuffle init load 2019-07-28 18:26:02 -07:00
Jared Broad
0f942149a0 Testing shuffling worker thread to algorithmSystemHandlers 2019-07-28 15:54:17 -07:00
Jared Broad
e86155c117 Shuffle init to set environment path inline 2019-07-28 15:12:54 -07:00
Jared Broad
1e8fdba3d9 Revert to master 2019-07-28 14:32:04 -07:00
Jared Broad
66a3f2e1d2 Move worker thread creation to launcher before job creation 2019-07-28 12:54:17 -07:00
Jared Broad
5a2adf2065 Remove lock, additional benchmarking 2019-07-28 10:57:22 -07:00
Jared Broad
2dd94f3687 Optimize python load times 2019-07-28 10:33:37 -07:00
6 changed files with 73 additions and 35 deletions

View File

@@ -156,30 +156,22 @@ namespace QuantConnect.AlgorithmFactory
return false;
}
try
{
PythonInitializer.Initialize(assemblyPath);
}
catch (Exception e)
{
Log.Error(e);
errorMessage = $"Loader.TryCreatePythonAlgorithm(): Failed to initialize PythonEngine. {e.Message}";
return false;
}
var pythonFile = new FileInfo(assemblyPath);
var moduleName = pythonFile.Name.Replace(".pyc", "").Replace(".py", "");
// Set the python path for loading python algorithms.
var pythonPath = new List<string>
{
pythonFile.Directory.FullName,
new DirectoryInfo(Environment.CurrentDirectory).FullName,
};
// Don't include an empty environment variable in pythonPath, otherwise the PYTHONPATH
// environment variable won't be used in the module import process
var pythonPathEnvironmentVariable = Environment.GetEnvironmentVariable("PYTHONPATH");
if (!string.IsNullOrEmpty(pythonPathEnvironmentVariable))
{
pythonPath.Add(pythonPathEnvironmentVariable);
}
Environment.SetEnvironmentVariable("PYTHONPATH", string.Join(OS.IsLinux ? ":" : ";", pythonPath));
try
{
PythonInitializer.Initialize();
algorithmInstance = new AlgorithmPythonWrapper(moduleName);
}
catch (Exception e)

View File

@@ -33,6 +33,7 @@ using QuantConnect.Securities.Option;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
namespace QuantConnect.AlgorithmFactory.Python.Wrappers
{
@@ -60,8 +61,16 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
{
Logging.Log.Trace($"AlgorithmPythonWrapper(): Python version {PythonEngine.Version}: Importing python module {moduleName}");
var benchmark = Stopwatch.StartNew();
var module = Py.Import(moduleName);
Logging.Log.Trace("AlgorithmPythonWrapper(): Python Import Completed: " + benchmark.Elapsed.TotalSeconds + "s.");
benchmark.Restart();
var pyList = module.Dir();
Logging.Log.Trace("AlgorithmPythonWrapper(): Module Dir Loaded: " + benchmark.Elapsed.TotalSeconds + "s.");
benchmark.Restart();
foreach (var name in pyList)
{
Type type;
@@ -92,6 +101,7 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
}
attr.Dispose();
}
Logging.Log.Trace("AlgorithmPythonWrapper(): Object invoke completed: " + benchmark.Elapsed.TotalSeconds + "s.");
module.Dispose();
pyList.Dispose();
// If _algorithm could not be set, throw exception

View File

@@ -14,6 +14,10 @@
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Python.Runtime;
namespace QuantConnect.Python
@@ -24,21 +28,44 @@ namespace QuantConnect.Python
public static class PythonInitializer
{
// Used to allow multiple Python unit and regression tests to be run in the same test run
private static bool _isBeginAllowThreadsCalled;
private static bool _initialized;
/// <summary>
/// Initialize the Python.NET library
/// </summary>
public static void Initialize()
public static void Initialize(string assemblyPath = "")
{
if (!_isBeginAllowThreadsCalled)
if (!_initialized)
{
if (assemblyPath != string.Empty)
{
// Set the python path for loading python algorithms.
var pythonPath = new List<string>
{
new FileInfo(assemblyPath).Directory.FullName,
new DirectoryInfo(Environment.CurrentDirectory).FullName,
};
// Don't include an empty environment variable in pythonPath, otherwise the PYTHONPATH
// environment variable won't be used in the module import process
var pythonPathEnvironmentVariable = Environment.GetEnvironmentVariable("PYTHONPATH");
if (!string.IsNullOrEmpty(pythonPathEnvironmentVariable))
{
pythonPath.Add(pythonPathEnvironmentVariable);
}
Environment.SetEnvironmentVariable("PYTHONPATH", string.Join(OS.IsLinux ? ":" : ";", pythonPath));
}
var benchmark = Stopwatch.StartNew();
PythonEngine.Initialize();
Logging.Log.Trace("PythonInitializer.Initialize(): Python Engine Initialized in " + benchmark.Elapsed.TotalSeconds + "s. Thread: " + System.Threading.Thread.CurrentThread.Name);
benchmark.Restart();
// required for multi-threading usage
PythonEngine.BeginAllowThreads();
_isBeginAllowThreadsCalled = true;
Logging.Log.Trace("PythonInitializer.Initialize(): Allow threading completed in " + benchmark.Elapsed.TotalSeconds + "s. Thread: " + System.Threading.Thread.CurrentThread.Name);
_initialized = true;
}
}
}

View File

@@ -124,8 +124,7 @@ namespace QuantConnect.Lean.Engine
var marketHoursDatabase = marketHoursDatabaseTask.Result;
// start worker thread
workerThread = new WorkerThread();
_algorithmHandlers.Setup.WorkerThread = workerThread;
workerThread = _algorithmHandlers.WorkerThread;
// Save algorithm to cache, load algorithm instance:
algorithm = _algorithmHandlers.Setup.CreateAlgorithmInstance(job, assemblyPath);

View File

@@ -79,6 +79,11 @@ namespace QuantConnect.Lean.Engine
/// </summary>
public IAlphaHandler Alphas { get; }
/// <summary>
/// Python algorithm worker thread.
/// </summary>
public WorkerThread WorkerThread { get; }
/// <summary>
/// Initializes a new instance of the <see cref="LeanEngineAlgorithmHandlers"/> class from the specified handlers
/// </summary>
@@ -148,6 +153,10 @@ namespace QuantConnect.Lean.Engine
FactorFileProvider = factorFileProvider;
DataProvider = dataProvider;
Alphas = alphas;
//Worker thread for python instances:
WorkerThread = new WorkerThread();
Setup.WorkerThread = WorkerThread;
}
/// <summary>

View File

@@ -25,6 +25,7 @@ using QuantConnect.Interfaces;
using QuantConnect.Lean.Engine;
using QuantConnect.Logging;
using QuantConnect.Packets;
using QuantConnect.Python;
using QuantConnect.Util;
namespace QuantConnect.Lean.Launcher
@@ -88,15 +89,6 @@ namespace QuantConnect.Lean.Launcher
//Setup packeting, queue and controls system: These don't do much locally.
leanEngineSystemHandlers.Initialize();
//-> Pull job from QuantConnect job queue, or, pull local build:
string assemblyPath;
var job = leanEngineSystemHandlers.JobQueue.NextJob(out assemblyPath);
if (job == null)
{
throw new Exception("Engine.Main(): Job was null.");
}
LeanEngineAlgorithmHandlers leanEngineAlgorithmHandlers;
try
{
@@ -108,6 +100,15 @@ namespace QuantConnect.Lean.Launcher
throw;
}
//-> Pull job from QuantConnect job queue, or, pull local build:
string assemblyPath;
var job = leanEngineSystemHandlers.JobQueue.NextJob(out assemblyPath);
if (job == null)
{
throw new Exception("Engine.Main(): Job was null.");
}
if (environment.EndsWith("-desktop"))
{
if (!File.Exists(Config.Get("desktop-exe")))