Skip to content

Commit 3b8bd7f

Browse files
author
ChrisMaunder
committed
V1.5.6.2. Bug fixes, perf improvements, and more CUDA support
1 parent 8848070 commit 3b8bd7f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+373
-282
lines changed

.vscode/tasks.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,28 @@
8888
"problemMatcher": "$msCompile"
8989
},
9090

91+
{
92+
"label": "build-tests", // Builds ONLY the .NET unit tests
93+
"type": "process",
94+
"group": "build",
95+
"command": "dotnet",
96+
"args": [
97+
"build",
98+
"${workspaceFolder}/tests/QueueServiceTests",
99+
"/property:GenerateFullPaths=true",
100+
"/consoleloggerparameters:NoSummary"
101+
],
102+
"problemMatcher": "$msCompile"
103+
},
104+
91105
{
92106
"label": "build-all-linux", // Builds all projects that can be built for Linux (ie not any Windows Forms apps)
93107
"group": "build",
94108
"dependsOrder": "sequence",
95109
"dependsOn": [
96110
"build-server",
97111
"build-analysisservices",
112+
"build-tests"
98113
]
99114
},
100115

@@ -105,7 +120,8 @@
105120
"dependsOn": [
106121
"build-server",
107122
"build-analysisservices",
108-
"build-explorer"
123+
"build-explorer",
124+
"build-tests"
109125
]
110126
},
111127

.wslconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Place this into /users/<username>
2+
3+
# Settings apply across all Linux distros running on WSL 2
4+
[wsl2]
5+
6+
# Limits VM memory to use no more than 12 GB, this can be set as whole numbers using GB or MB
7+
# The default is 50% of available RAM and 8GB isn't (currently) enough for CodeProject AI Server GPU
8+
memory=12GB
9+
10+
# Sets amount of swap storage space to 8GB, default is 25% of available RAM
11+
swap=8GB

CodeProject.AI.sln

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AnalysisLayer", "AnalysisLa
2424
EndProjectSection
2525
EndProject
2626
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Installers", "Installers", "{D885EE64-C1BD-44D6-84D8-1E46806298D9}"
27+
ProjectSection(SolutionItems) = preProject
28+
Installers\install_CUDnn.bat = Installers\install_CUDnn.bat
29+
EndProjectSection
2730
EndProject
2831
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Javascript", "Javascript", "{3A860CDD-94B9-4002-BA08-87E8822DDE50}"
2932
ProjectSection(SolutionItems) = preProject
@@ -64,7 +67,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{CB26AB
6467
EndProject
6568
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{460DB5C8-46F3-4407-A2DF-D9063D14493A}"
6669
ProjectSection(SolutionItems) = preProject
67-
commands.json = commands.json
6870
src\endtimer.bat = src\endtimer.bat
6971
src\kill_dotnet.bat = src\kill_dotnet.bat
7072
src\kill_dotnet.sh = src\kill_dotnet.sh
@@ -193,7 +195,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Objects", "Objects", "{4ED5
193195
EndProject
194196
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObjectDetectionNet", "src\AnalysisLayer\ObjectDetectionNet\ObjectDetectionNet.csproj", "{25D75AFE-BEC9-43BF-BE44-B9068FF8E395}"
195197
EndProject
196-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeProject.SenseAI.API.Server.Backend.Tests", "tests\QueueServiceTests\CodeProject.SenseAI.API.Server.Backend.Tests.csproj", "{F94FBD1C-02FB-4169-8C26-2D52234D4311}"
198+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeProject.AI.API.Server.Backend.Tests", "tests\QueueServiceTests\CodeProject.AI.API.Server.Backend.Tests.csproj", "{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}"
197199
EndProject
198200
Global
199201
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -299,14 +301,14 @@ Global
299301
{25D75AFE-BEC9-43BF-BE44-B9068FF8E395}.Release|Any CPU.Build.0 = Release|Any CPU
300302
{25D75AFE-BEC9-43BF-BE44-B9068FF8E395}.Release|x86.ActiveCfg = Release|Any CPU
301303
{25D75AFE-BEC9-43BF-BE44-B9068FF8E395}.Release|x86.Build.0 = Release|Any CPU
302-
{F94FBD1C-02FB-4169-8C26-2D52234D4311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
303-
{F94FBD1C-02FB-4169-8C26-2D52234D4311}.Debug|Any CPU.Build.0 = Debug|Any CPU
304-
{F94FBD1C-02FB-4169-8C26-2D52234D4311}.Debug|x86.ActiveCfg = Debug|Any CPU
305-
{F94FBD1C-02FB-4169-8C26-2D52234D4311}.Debug|x86.Build.0 = Debug|Any CPU
306-
{F94FBD1C-02FB-4169-8C26-2D52234D4311}.Release|Any CPU.ActiveCfg = Release|Any CPU
307-
{F94FBD1C-02FB-4169-8C26-2D52234D4311}.Release|Any CPU.Build.0 = Release|Any CPU
308-
{F94FBD1C-02FB-4169-8C26-2D52234D4311}.Release|x86.ActiveCfg = Release|Any CPU
309-
{F94FBD1C-02FB-4169-8C26-2D52234D4311}.Release|x86.Build.0 = Release|Any CPU
304+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
305+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
306+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}.Debug|x86.ActiveCfg = Debug|Any CPU
307+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}.Debug|x86.Build.0 = Debug|Any CPU
308+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
309+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}.Release|Any CPU.Build.0 = Release|Any CPU
310+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}.Release|x86.ActiveCfg = Release|Any CPU
311+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B}.Release|x86.Build.0 = Release|Any CPU
310312
EndGlobalSection
311313
GlobalSection(SolutionProperties) = preSolution
312314
HideSolutionNode = FALSE
@@ -346,7 +348,7 @@ Global
346348
{C2EFFA0A-E8EA-4AFE-8599-FC28CB7864FB} = {B10B59B5-9F63-41C2-BFBB-6C7311DC4E99}
347349
{4ED567B5-C28D-48BB-AEDC-864E2B2C7204} = {B10B59B5-9F63-41C2-BFBB-6C7311DC4E99}
348350
{25D75AFE-BEC9-43BF-BE44-B9068FF8E395} = {156BFEDA-D477-43B2-92DA-FCC9BAF1F893}
349-
{F94FBD1C-02FB-4169-8C26-2D52234D4311} = {D982BD8C-2257-413B-8513-8043AB3035F3}
351+
{031F17E0-BE84-42AF-B9FE-4F928CB03D1B} = {D982BD8C-2257-413B-8513-8043AB3035F3}
350352
EndGlobalSection
351353
GlobalSection(ExtensibilityGlobals) = postSolution
352354
SolutionGuid = {83740BD9-AEEF-49C7-A722-D7703D3A38CB}

Installers/Dev/setup_dev_env_linux.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ useColor="true"
5656
enableGPU="false"
5757

5858
# are we ready to support CUDA enabled GPUs?
59-
ssupportCUDA="false"
59+
supportCUDA="false"
6060

6161
# verbosity can be: quiet | info | loud
6262
verbosity="quiet"

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ transfer, and is easy to use.
2020

2121
</div>
2222

23+
2324
# Why
2425

2526
1. AI programming is something every single developer should be aware of. We wanted a fun project we could use to help teach developers and get them involved in AI. We'll be using CodeProject.AI as a focus for articles and exploration to make it fun and painless to learn AI programming.
@@ -90,7 +91,7 @@ It can detect stuff!
9091

9192
CodeProject.AI can currently
9293

93-
- Detect objects in images
94+
- Detect objects in images, including using custom models
9495
- Detect faces in images
9596
- Detect the type of scene represented in an image
9697
- Recognise faces that have been registered with the service
@@ -112,13 +113,11 @@ We will be constantly expanding the feature list.
112113

113114
#### Supported Development Environments
114115

115-
116116
This current release works in Visual Studio 2019+ on Windows 10+, and Visual Studio Code on Windows 10+. Ubuntu and macOS (both Intel and Apple Silicon).
117117

118118
The current release supports CPU on each platform, as well as nVidia CUDA GPUs on Windows. Future releases will expand GPU support to Docker and other cards.
119119

120120

121-
122121
## How to Guides
123122

124123
- [Installing CodeProject.AI on your machine](https://www.codeproject.com/ai/docs/why/install_on_windows.html). For those who have CodeProject.AI integrated with Home Assist or Blue Iris

THIRD-PARTY-NOTICES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
352352
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
353353
POSSIBILITY OF SUCH DAMAGE.
354354

355+
355356
### Swashbuckle.AspNetCore
356357
##### Generate beautiful API documentation
357358
https://github.com/domaindrivendev/Swashbuckle.AspNetCore

src/API/Server/FrontEnd/BackendProcessRunner.cs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
265265
loggerIsValid = false;
266266
}
267267

268-
bool launchAnalysisServices = _config.GetValue("LaunchAnalysisServices", true);
268+
bool launchAnalysisServices = _config.GetValue("LaunchAnalysisServices", true);
269+
int launchAnalysisServicesDelaySecs = _config.GetValue("LaunchAnalysisServicesDelaySecs", 3);
269270

270271
// Setup routes. Do this first so they are active during debug without launching services.
271272
foreach (var entry in _modules!)
@@ -310,7 +311,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
310311

311312
// Let's make sure the front end is up and running before we start the backend
312313
// analysis services
313-
await Task.Delay(TimeSpan.FromSeconds(3), stoppingToken);
314+
await Task.Delay(TimeSpan.FromSeconds(launchAnalysisServicesDelaySecs), stoppingToken);
314315

315316
if (loggerIsValid)
316317
{
@@ -337,7 +338,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
337338
continue;
338339

339340
if (status.Status == ProcessStatusType.NotEnabled)
340-
_logger.LogWarning($"Not starting {module.Name} (Not set as enabled)");
341+
{
342+
// _logger.LogWarning($"Not starting {module.Name} (Not set as enabled)");
343+
}
344+
else
345+
{
346+
_logger.LogWarning($"Attempting to start {module.Name}, Runtime: {module.Runtime}, FilePath: {module.FilePath}");
347+
}
341348

342349
if (status.Status == ProcessStatusType.Enabled && !string.IsNullOrEmpty(module.FilePath))
343350
{
@@ -348,11 +355,11 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
348355
if (!string.IsNullOrWhiteSpace(routeInfo.Queue))
349356
_queueServices.EnsureQueueExists(routeInfo.Queue);
350357

351-
ProcessStartInfo procStartInfo = CreateProcessStartInfo(module, moduleId);
352-
353-
// Start the process
354358
try
355359
{
360+
// Start the process
361+
ProcessStartInfo procStartInfo = CreateProcessStartInfo(module, moduleId);
362+
356363
if (loggerIsValid)
357364
_logger.LogTrace($"Starting {ShrinkPath(procStartInfo.FileName, 50)} {ShrinkPath(procStartInfo.Arguments, 50)}");
358365

@@ -404,7 +411,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
404411
if (string.IsNullOrEmpty(error))
405412
error = "No error provided";
406413

407-
if (error != "info: Microsoft.Hosting.Lifetime[0]")
414+
if (error.Contains("LoadLibrary failed with error 126") &&
415+
error.Contains("onnxruntime_providers_cuda.dll"))
416+
{
417+
error = "Attempted to load ONNX runtime CUDA provider. No luck, moving on...";
418+
_logger.LogInformation(filename + error);
419+
}
420+
else if (error != "info: Microsoft.Hosting.Lifetime[0]")
408421
{
409422
// TOTAL HACK. ONNX/Tensorflow output is WAY too verbose for an error
410423
if (error.Contains("I tensorflow/cc/saved_model/reader.cc:") ||
@@ -415,6 +428,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
415428
}
416429
};
417430

431+
status.Status = ProcessStatusType.Starting;
418432
if (!process.Start())
419433
{
420434
process = null;
@@ -423,15 +437,20 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
423437

424438
if (process is not null)
425439
{
440+
status.Started = DateTime.UtcNow;
426441
process.BeginOutputReadLine();
427442
process.BeginErrorReadLine();
428443

429444
if (loggerIsValid)
430445
_logger.LogInformation($"Started {module.Name} backend");
431446

432447
_runningProcesses.Add(process);
433-
status.Status = ProcessStatusType.Started;
434-
status.Started = DateTime.UtcNow;
448+
449+
int postStartPauseSecs = 5; // module.PostStartPauseSecs ?? 5;
450+
451+
// Trying to reduce startup CPU and Memory for Docker
452+
await Task.Delay(TimeSpan.FromSeconds(postStartPauseSecs));
453+
status.Status = ProcessStatusType.Started;
435454
}
436455
else
437456
{
@@ -446,6 +465,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
446465
if (loggerIsValid)
447466
{
448467
_logger.LogError(ex, $"Error trying to start { module.Name} ({module.FilePath})");
468+
_logger.LogError(ex.Message);
469+
_logger.LogError(ex.StackTrace);
449470
}
450471
#if DEBUG
451472
_logger.LogError($" *** Did you setup the Development environment?");
@@ -485,8 +506,16 @@ private ProcessStartInfo CreateProcessStartInfo(ModuleConfig module, string modu
485506
}
486507

487508
// Setup the process we're going to launch
509+
#if Windows
510+
// Windows paths can have spaces so need quotes
511+
var executableName = $"\"{filePath}\"";
512+
#else
513+
// the I'm assuming the directories don't have spaces in Linux and MacOS
514+
// because the Process.Start is choking on the quotes
515+
var executableName = filePath;
516+
#endif
488517
ProcessStartInfo? procStartInfo = (command == "execute" || command == "launcher")
489-
? new ProcessStartInfo($"\"{filePath}\"")
518+
? new ProcessStartInfo(executableName)
490519
{
491520
UseShellExecute = false,
492521
WorkingDirectory = workingDirectory,
@@ -563,8 +592,8 @@ private bool IsEnabled(ModuleConfig module)
563592
return _frontendOptions.PYTHON_PATH?.Replace(PythonRuntimeMarker, launcher);
564593
}
565594

566-
if (runtime == "dotnet")
567-
return "dotnet";
595+
if (runtime == "dotnet" || runtime == "execute" || runtime == "launcher")
596+
return runtime;
568597

569598
return null;
570599
}

src/API/Server/FrontEnd/Config/ModuleCollection.cs

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ public class ModuleConfig
5353
/// </summary>
5454
public string? Command { get; set; }
5555

56+
/*
57+
/// <summary>
58+
/// Gets or sets the number of seconds this module should pause after starting to ensure
59+
/// any resources that require startup (eg GPUs) are fully activated before moving on.
60+
/// </summary>
61+
public int? PostStartPauseSecs { get; set; }
62+
*/
63+
5664
/// <summary>
5765
/// Gets or sets the path to the startup file relative to the module directory.
5866
/// </summary>
@@ -96,40 +104,6 @@ public class ModuleConfig
96104
public string[] Platforms { get; set; } = Array.Empty<string>();
97105

98106
/*
99-
/// <summary>
100-
/// Gets or sets the time this module was started.
101-
/// </summary>
102-
// TODO: Move the status info to another class that references or includes
103-
// the module coniguration, if needed.
104-
public DateTime? Started { get; set; } = null;
105-
106-
/// <summary>
107-
/// Gets or sets the latest time a request from this module was spotted by the queue manager.
108-
/// </summary>
109-
// TODO: Move the status info to another class that references or includes
110-
// the module coniguration, if needed.
111-
public DateTime? LastSeen { get; set; } = null;
112-
113-
/// <summary>
114-
/// Gets a value indicating whether this process is currently active
115-
/// </summary>
116-
// TODO: Move the status info to another class that references or includes
117-
// the module coniguration, if needed.
118-
public bool Running
119-
{
120-
get
121-
{
122-
return LastSeen != null && (DateTime.UtcNow - LastSeen!) < TimeSpan.FromSeconds(65);
123-
}
124-
}
125-
126-
/// <summary>
127-
/// Gets or sets the number of requests processed
128-
/// </summary>
129-
// TODO: Move the status info to another class that references or includes
130-
// the module coniguration, if needed.
131-
public int? Processed { get; set; } = 0;
132-
133107
/// <summary>
134108
/// Gets or sets the name of the hardware acceleration provider.
135109
/// </summary>

src/API/Server/FrontEnd/Controllers/LogController.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ public ResponseBase AddLog([FromForm] string? entry,
5151
msg += "[[" + category + "]]";
5252
if (!string.IsNullOrWhiteSpace(label))
5353
msg += "{{" + label + "}}";
54+
55+
if (entry.Contains("LoadLibrary failed with error 126") &&
56+
entry.Contains("onnxruntime_providers_cuda.dll"))
57+
{
58+
entry = "Attempted to load ONNX runtime CUDA provider. No luck, moving on...";
59+
log_level = LogLevel.Information;
60+
}
61+
5462
msg += entry;
5563

5664
switch (log_level)

src/API/Server/FrontEnd/Controllers/StatusController.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ public ResponseBase ListAnalysisStatus()
163163
// List them out and return the status
164164
var response = new AnalysisServicesStatusResponse
165165
{
166-
statuses = backend.ProcessStatuses.Values.ToList()
166+
statuses = backend.ProcessStatuses
167+
.Values
168+
.Where(module => module.Status != ProcessStatusType.NotEnabled)
169+
.ToList()
167170
};
168171

169172
return response;

0 commit comments

Comments
 (0)