Skip to content

Commit f4a71c8

Browse files
Code portability
1 parent d161188 commit f4a71c8

File tree

1 file changed

+105
-41
lines changed

1 file changed

+105
-41
lines changed

neural/neuralfit.pas

+105-41
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
// This unit is under development - do not use it.
22
unit neuralfit;
33

4-
{$mode objfpc}{$H+}
4+
{$IFDEF FPC}
5+
{$mode objfpc}
6+
{$H+}
7+
{$DEFINE HASTHREADS}
8+
{$ENDIF}
59

610
interface
711

812
uses
9-
Classes, SysUtils, neuralnetwork, neuralvolume, MTProcs;
13+
Classes, SysUtils, neuralnetwork, neuralvolume
14+
{$IFDEF HASTHREADS}, MTProcs{$ENDIF}
15+
;
1016

1117
type
1218
TCustomLearningRateScheduleFn = function(Epoch: integer): single;
1319
TCustomLearningRateScheduleObjFn = function(Epoch: integer): single of object;
1420

21+
{$IFNDEF HASTHREADS}
22+
TMultiThreadProcItem = TObject;
23+
{$ENDIF}
24+
1525
/// This is a base class. Do not use it directly.
1626
TNeuralFitBase = class(TMObject)
1727
protected
@@ -28,7 +38,7 @@ TNeuralFitBase = class(TMObject)
2838
FGlobalTotalLoss: single;
2939
FGlobalErrorSum: single;
3040
FFinishedThread: TNNetVolume;
31-
FCritSec: TRTLCriticalSection;
41+
{$IFDEF HASTHREADS}FCritSec: TRTLCriticalSection;{$ENDIF}
3242
FMultipleSamplesAtValidation: boolean;
3343
FDataAugmentation: boolean;
3444
FVerbose: boolean;
@@ -205,6 +215,9 @@ procedure TNeuralFit.Fit(pNN: TNNet; pTrainingVolumes, pValidationVolumes,
205215
ValidationRecord: TNeuralFloat;
206216
iEpochCount: integer;
207217
begin
218+
{$IFNDEF HASTHREADS}
219+
FMaxThreadNum := 1;
220+
{$ENDIF}
208221
iEpochCount := FInitialEpoch;
209222
FCurrentLearningRate := FInitialLearningRate;
210223
FTrainingVolumes := pTrainingVolumes;
@@ -296,7 +309,11 @@ procedure TNeuralFit.Fit(pNN: TNNet; pTrainingVolumes, pValidationVolumes,
296309
FGlobalErrorSum := 0;
297310
FFinishedThread.Fill(0);
298311
FNN.ClearTime();
312+
{$IFDEF HASTHREADS}
299313
ProcThreadPool.DoParallel(@RunNNThread, 0, FThreadNN.Count-1, Nil, FThreadNN.Count);
314+
{$ELSE}
315+
RunNNThread(0, nil, Self);
316+
{$ENDIF}
300317
if FClipDelta > 0 then
301318
begin
302319
MaxDelta := FNN.ForceMaxAbsoluteDelta(FClipDelta);
@@ -382,7 +399,11 @@ procedure TNeuralFit.Fit(pNN: TNNet; pTrainingVolumes, pValidationVolumes,
382399
FGlobalTotalLoss := 0;
383400
FGlobalErrorSum := 0;
384401
FMessageProc('Starting Validation.');
402+
{$IFDEF HASTHREADS}
385403
ProcThreadPool.DoParallel(@TestNNThread, 0, FThreadNN.Count-1, Nil, FThreadNN.Count);
404+
{$ELSE}
405+
TestNNThread(0, nil, Self);
406+
{$ENDIF}
386407

387408
FGlobalTotal := (FGlobalHit + FGlobalMiss);
388409
if FGlobalTotal > 0 then
@@ -433,7 +454,11 @@ procedure TNeuralFit.Fit(pNN: TNNet; pTrainingVolumes, pValidationVolumes,
433454
FGlobalTotalLoss := 0;
434455
FGlobalErrorSum := 0;
435456
FMessageProc('Starting Testing.');
457+
{$IFDEF HASTHREADS}
436458
ProcThreadPool.DoParallel(@TestNNThread, 0, FThreadNN.Count-1, Nil, FThreadNN.Count);
459+
{$ELSE}
460+
TestNNThread(0, nil, Self);
461+
{$ENDIF}
437462

438463
FGlobalTotal := (FGlobalHit + FGlobalMiss);
439464
if FGlobalTotal > 0 then
@@ -564,11 +589,11 @@ procedure TNeuralFit.RunNNThread(Index: PtrInt; Data: Pointer;
564589
LocalNN.GetOutput( pOutput );
565590
LocalNN.Backpropagate( FTrainingVolumes[ElementIdx].O );
566591

567-
LocalErrorSum += vOutput.SumDiff( pOutput );
592+
LocalErrorSum := LocalErrorSum + vOutput.SumDiff( pOutput );
568593

569594
//TODO: calculate loss here!
570595
CurrentLoss := 0;
571-
LocalTotalLoss += CurrentLoss;
596+
LocalTotalLoss := LocalTotalLoss + CurrentLoss;
572597

573598
if Assigned(FInferHitFn) then
574599
begin
@@ -589,25 +614,35 @@ procedure TNeuralFit.RunNNThread(Index: PtrInt; Data: Pointer;
589614
begin
590615
while FFinishedThread.FData[Index + 1] = 0 do;
591616
LocalNN.SumDeltasNoChecks(FThreadNN[Index + 1]);
617+
{$IFDEF FPC}
592618
FFinishedThread.FData[Index] += FFinishedThread.FData[Index + 1];
619+
{$ELSE}
620+
FFinishedThread.FData[Index] := FFinishedThread.FData[Index] +
621+
FFinishedThread.FData[Index + 1];
622+
{$ENDIF}
593623
end;
594624
end;
595-
FFinishedThread.FData[Index] += 1;
625+
FFinishedThread.FData[Index] := FFinishedThread.FData[Index] + 1;
596626
if Index and 3 = 0 then
597627
begin
598628
if Index + 2 < FThreadNum then
599629
begin
600630
while FFinishedThread.FData[Index + 2] = 0 do;
601631
LocalNN.SumDeltasNoChecks(FThreadNN[Index + 2]);
632+
{$IFDEF FPC}
602633
FFinishedThread.FData[Index] += FFinishedThread.FData[Index + 2];
634+
{$ELSE}
635+
FFinishedThread.FData[Index] := FFinishedThread.FData[Index] +
636+
FFinishedThread.FData[Index + 2];
637+
{$ENDIF}
603638
end;
604639
end;
605640

606-
EnterCriticalSection(FCritSec);
607-
FGlobalHit += LocalHit;
608-
FGlobalMiss += LocalMiss;
609-
FGlobalTotalLoss += LocalTotalLoss;
610-
FGlobalErrorSum += LocalErrorSum;
641+
{$IFDEF HASTHREADS}EnterCriticalSection(FCritSec);{$ENDIF}
642+
FGlobalHit := FGlobalHit + LocalHit;
643+
FGlobalMiss := FGlobalMiss + LocalMiss;
644+
FGlobalTotalLoss := FGlobalTotalLoss + LocalTotalLoss;
645+
FGlobalErrorSum := FGlobalErrorSum + LocalErrorSum;
611646

612647
FNN.ForwardTime := FNN.ForwardTime + LocalNN.ForwardTime;
613648
FNN.BackwardTime := FNN.BackwardTime + LocalNN.BackwardTime;
@@ -616,7 +651,7 @@ procedure TNeuralFit.RunNNThread(Index: PtrInt; Data: Pointer;
616651
{$ELSE}
617652
if Index and 3 = 0 then FNN.SumDeltasNoChecks(LocalNN);
618653
{$ENDIF}
619-
LeaveCriticalSection(FCritSec);
654+
{$IFDEF HASTHREADS}LeaveCriticalSection(FCritSec);{$ENDIF}
620655
vInput.Free;
621656
vOutput.Free;
622657
pOutput.Free;
@@ -660,7 +695,7 @@ procedure TNeuralFit.TestNNThread(Index: PtrInt; Data: Pointer;
660695
LocalNN.Compute( vInput );
661696
LocalNN.GetOutput( pOutput );
662697

663-
LocalErrorSum += FWorkingVolumes[ElementIdx].O.SumDiff( pOutput );
698+
LocalErrorSum := LocalErrorSum + FWorkingVolumes[ElementIdx].O.SumDiff( pOutput );
664699

665700
if Assigned(FInferHitFn) then
666701
begin
@@ -675,16 +710,16 @@ procedure TNeuralFit.TestNNThread(Index: PtrInt; Data: Pointer;
675710
end;
676711

677712
if Assigned(FLossFn)
678-
then LocalTotalLoss += FLossFn(FWorkingVolumes[ElementIdx].O);
713+
then LocalTotalLoss := LocalTotalLoss + FLossFn(FWorkingVolumes[ElementIdx].O);
679714
end; // of for
680715
LocalNN.EnableDropouts(true);
681716

682-
EnterCriticalSection(FCritSec);
683-
FGlobalHit += LocalHit;
684-
FGlobalMiss += LocalMiss;
685-
FGlobalTotalLoss += LocalTotalLoss;
686-
FGlobalErrorSum += LocalErrorSum;
687-
LeaveCriticalSection(FCritSec);
717+
{$IFDEF HASTHREADS}EnterCriticalSection(FCritSec);{$ENDIF}
718+
FGlobalHit := FGlobalHit + LocalHit;
719+
FGlobalMiss := FGlobalMiss + LocalMiss;
720+
FGlobalTotalLoss := FGlobalTotalLoss + LocalTotalLoss;
721+
FGlobalErrorSum := FGlobalErrorSum + LocalErrorSum;
722+
{$IFDEF HASTHREADS}LeaveCriticalSection(FCritSec);{$ENDIF}
688723

689724
LocalFrequency.Free;
690725
vInput.Free;
@@ -708,9 +743,13 @@ constructor TNeuralFitBase.Create();
708743
begin
709744
inherited Create();
710745
FFinishedThread := TNNetVolume.Create();
746+
{$IFDEF HASTHREADS}
711747
FMaxThreadNum := ProcThreadPool.MaxThreadCount;
712-
FDataAugmentation := true;
713748
InitCriticalSection(FCritSec);
749+
{$ELSE}
750+
FMaxThreadNum := 1;
751+
{$ENDIF}
752+
FDataAugmentation := true;
714753
FMultipleSamplesAtValidation := true;
715754
FVerbose := true;
716755
FStaircaseEpochs := 1;
@@ -733,7 +772,9 @@ constructor TNeuralFitBase.Create();
733772

734773
destructor TNeuralFitBase.Destroy();
735774
begin
775+
{$IFDEF HASTHREADS}
736776
DoneCriticalSection(FCritSec);
777+
{$ENDIF}
737778
FFinishedThread.Free;
738779
inherited Destroy();
739780
end;
@@ -810,6 +851,9 @@ procedure TNeuralImageFit.Fit(pNN: TNNet;
810851
ValidationRecord: TNeuralFloat;
811852
iEpochCount: integer;
812853
begin
854+
{$IFNDEF HASTHREADS}
855+
FMaxThreadNum := 1;
856+
{$ENDIF}
813857
iEpochCount := FInitialEpoch;
814858
FCurrentLearningRate := FInitialLearningRate;
815859
FImgVolumes := pImgVolumes;
@@ -902,7 +946,11 @@ procedure TNeuralImageFit.Fit(pNN: TNNet;
902946
FGlobalErrorSum := 0;
903947
FFinishedThread.Fill(0);
904948
FNN.ClearTime();
949+
{$IFDEF HASTHREADS}
905950
ProcThreadPool.DoParallel(@RunNNThread, 0, FThreadNN.Count-1, Nil, FThreadNN.Count);
951+
{$ELSE}
952+
RunNNThread(0, nil, Self);
953+
{$ENDIF}
906954
if FClipDelta > 0 then
907955
begin
908956
MaxDelta := FNN.ForceMaxAbsoluteDelta(FClipDelta);
@@ -988,7 +1036,11 @@ procedure TNeuralImageFit.Fit(pNN: TNNet;
9881036
FGlobalTotalLoss := 0;
9891037
FGlobalErrorSum := 0;
9901038
FMessageProc('Starting Validation.');
1039+
{$IFDEF HASTHREADS}
9911040
ProcThreadPool.DoParallel(@TestNNThread, 0, FThreadNN.Count-1, Nil, FThreadNN.Count);
1041+
{$ELSE}
1042+
TestNNThread(0, nil, Self);
1043+
{$ENDIF}
9921044

9931045
FGlobalTotal := (FGlobalHit + FGlobalMiss);
9941046
if (FGlobalTotal > 0) then
@@ -1039,7 +1091,11 @@ procedure TNeuralImageFit.Fit(pNN: TNNet;
10391091
FGlobalTotalLoss := 0;
10401092
FGlobalErrorSum := 0;
10411093
FMessageProc('Starting Testing.');
1094+
{$IFDEF HASTHREADS}
10421095
ProcThreadPool.DoParallel(@TestNNThread, 0, FThreadNN.Count-1, Nil, FThreadNN.Count);
1096+
{$ELSE}
1097+
TestNNThread(0, nil, Self);
1098+
{$ENDIF}
10431099

10441100
FGlobalTotal := (FGlobalHit + FGlobalMiss);
10451101
if (FGlobalTotal > 0) then
@@ -1203,7 +1259,7 @@ procedure TNeuralImageFit.RunNNThread(Index: PtrInt; Data: Pointer;
12031259
then vOutput.SetClassForSoftMax( ImgInput.Tag )
12041260
else vOutput.SetClass( ImgInput.Tag, +0.9, -0.1);
12051261

1206-
LocalErrorSum += vOutput.SumDiff( pOutput );
1262+
LocalErrorSum := LocalErrorSum + vOutput.SumDiff( pOutput );
12071263
OutputValue := pOutput.FData[ ImgInput.Tag ];
12081264
if Not(FIsSoftmax) then
12091265
begin
@@ -1224,7 +1280,7 @@ procedure TNeuralImageFit.RunNNThread(Index: PtrInt; Data: Pointer;
12241280
WriteLn('Error - invalid output value:',OutputValue);
12251281
CurrentLoss := 1;
12261282
end;
1227-
LocalTotalLoss += CurrentLoss;
1283+
LocalTotalLoss := LocalTotalLoss + CurrentLoss;
12281284

12291285
if pOutput.GetClass() = FImgVolumes[ImgIdx].Tag then
12301286
begin
@@ -1242,26 +1298,35 @@ procedure TNeuralImageFit.RunNNThread(Index: PtrInt; Data: Pointer;
12421298
begin
12431299
while FFinishedThread.FData[Index + 1] = 0 do;
12441300
LocalNN.SumDeltasNoChecks(FThreadNN[Index + 1]);
1301+
{$IFDEF FPC}
12451302
FFinishedThread.FData[Index] += FFinishedThread.FData[Index + 1];
1303+
{$ELSE}
1304+
FFinishedThread.FData[Index] := FFinishedThread.FData[Index] +
1305+
FFinishedThread.FData[Index + 1];
1306+
{$ENDIF}
12461307
end;
12471308
end;
1248-
FFinishedThread.FData[Index] += 1;
1309+
FFinishedThread.FData[Index] := FFinishedThread.FData[Index] + 1;
12491310
if Index and 3 = 0 then
12501311
begin
12511312
if Index + 2 < FThreadNum then
12521313
begin
12531314
while FFinishedThread.FData[Index + 2] = 0 do;
12541315
LocalNN.SumDeltasNoChecks(FThreadNN[Index + 2]);
1316+
{$IFDEF FPC}
12551317
FFinishedThread.FData[Index] += FFinishedThread.FData[Index + 2];
1318+
{$ELSE}
1319+
FFinishedThread.FData[Index] := FFinishedThread.FData[Index] +
1320+
FFinishedThread.FData[Index + 2];
1321+
{$ENDIF}
12561322
end;
12571323
end;
1258-
// WriteLn('Index:',Index,' [',FFinishedThread.FData[Index],']');
12591324

1260-
EnterCriticalSection(FCritSec);
1261-
FGlobalHit += LocalHit;
1262-
FGlobalMiss += LocalMiss;
1263-
FGlobalTotalLoss += LocalTotalLoss;
1264-
FGlobalErrorSum += LocalErrorSum;
1325+
{$IFDEF HASTHREADS}EnterCriticalSection(FCritSec);{$ENDIF}
1326+
FGlobalHit := FGlobalHit + LocalHit;
1327+
FGlobalMiss := FGlobalMiss + LocalMiss;
1328+
FGlobalTotalLoss := FGlobalTotalLoss + LocalTotalLoss;
1329+
FGlobalErrorSum := FGlobalErrorSum + LocalErrorSum;
12651330

12661331
FNN.ForwardTime := FNN.ForwardTime + LocalNN.ForwardTime;
12671332
FNN.BackwardTime := FNN.BackwardTime + LocalNN.BackwardTime;
@@ -1270,7 +1335,7 @@ procedure TNeuralImageFit.RunNNThread(Index: PtrInt; Data: Pointer;
12701335
{$ELSE}
12711336
if Index and 3 = 0 then FNN.SumDeltasNoChecks(LocalNN);
12721337
{$ENDIF}
1273-
LeaveCriticalSection(FCritSec);
1338+
{$IFDEF HASTHREADS}LeaveCriticalSection(FCritSec);{$ENDIF}
12741339
ImgInputCp.Free;
12751340
ImgInput.Free;
12761341
vOutput.Free;
@@ -1356,10 +1421,10 @@ procedure TNeuralImageFit.TestNNThread(Index: PtrInt; Data: Pointer;
13561421
end;
13571422

13581423
vOutput.SetClassForSoftMax( ImgInput.Tag );
1359-
LocalErrorSum += vOutput.SumDiff( pOutput );
1424+
LocalErrorSum := LocalErrorSum + vOutput.SumDiff( pOutput );
13601425

13611426
OutputValue := pOutput.FData[ ImgInput.Tag ];
1362-
if Not(FIsSoftmax) then OutputValue += 0.5001;
1427+
if Not(FIsSoftmax) then OutputValue := OutputValue + 0.5001;
13631428

13641429
if (OutputValue > 0) then
13651430
begin
@@ -1370,7 +1435,7 @@ procedure TNeuralImageFit.TestNNThread(Index: PtrInt; Data: Pointer;
13701435
WriteLn('Error - invalid output value:',OutputValue);
13711436
CurrentLoss := 1;
13721437
end;
1373-
LocalTotalLoss += CurrentLoss;
1438+
LocalTotalLoss := LocalTotalLoss + CurrentLoss;
13741439

13751440
PredictedClass := pOutput.GetClass();
13761441
if PredictedClass = ImgInput.Tag then
@@ -1384,12 +1449,12 @@ procedure TNeuralImageFit.TestNNThread(Index: PtrInt; Data: Pointer;
13841449
end; // of for
13851450
LocalNN.EnableDropouts(true);
13861451

1387-
EnterCriticalSection(FCritSec);
1388-
FGlobalHit += LocalHit;
1389-
FGlobalMiss += LocalMiss;
1390-
FGlobalTotalLoss += LocalTotalLoss;
1391-
FGlobalErrorSum += LocalErrorSum;
1392-
LeaveCriticalSection(FCritSec);
1452+
{$IFDEF HASTHREADS}EnterCriticalSection(FCritSec);{$ENDIF}
1453+
FGlobalHit := FGlobalHit + LocalHit;
1454+
FGlobalMiss := FGlobalMiss + LocalMiss;
1455+
FGlobalTotalLoss := FGlobalTotalLoss + LocalTotalLoss;
1456+
FGlobalErrorSum := FGlobalErrorSum + LocalErrorSum;
1457+
{$IFDEF HASTHREADS}LeaveCriticalSection(FCritSec);{$ENDIF}
13931458

13941459
sumOutput.Free;
13951460
ImgInputCp.Free;
@@ -1444,4 +1509,3 @@ procedure TNeuralImageFit.ClassifyImage(pNN: TNNet; pImgInput, pOutput: TNNetVol
14441509
end;
14451510

14461511
end.
1447-

0 commit comments

Comments
 (0)