1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
21 *************************************************************************/
24 * L1Straight Equation Solving Routines
25 * Copyright (c) 2017-2024 Oleh Derevenko, odar@eleks.com (change all "a" to "e")
28 #include <ode/common.h>
29 #include <ode/matrix.h>
30 #include <ode/matrix_coop.h>
32 #include "threaded_solver_ldlt.h"
33 #include "threading_base.h"
34 #include "resource_control.h"
37 #include "fastlsolve_impl.h"
41 void ThreadedEquationSolverLDLT::estimateCooperativeSolvingL1StraightResourceRequirements(
42 dxResourceRequirementDescriptor
*summaryRequirementsDescriptor
,
43 unsigned allowedThreadCount
, unsigned rowCount
)
45 dxThreadingBase
*threading
= summaryRequirementsDescriptor
->getrelatedThreading();
46 unsigned limitedThreadCount
= restrictSolvingL1StraightAllowedThreadCount(threading
, allowedThreadCount
, rowCount
);
48 if (limitedThreadCount
> 1)
50 doEstimateCooperativeSolvingL1StraightResourceRequirementsValidated(summaryRequirementsDescriptor
, allowedThreadCount
, rowCount
);
55 void ThreadedEquationSolverLDLT::cooperativelySolveL1Straight(
56 dxRequiredResourceContainer
*resourceContainer
, unsigned allowedThreadCount
,
57 const dReal
*L
, dReal
*b
, unsigned rowCount
, unsigned rowSkip
)
59 dAASSERT(rowCount
!= 0);
61 dxThreadingBase
*threading
= resourceContainer
->getThreadingInstance();
62 unsigned limitedThreadCount
= restrictSolvingL1StraightAllowedThreadCount(threading
, allowedThreadCount
, rowCount
);
64 if (limitedThreadCount
<= 1)
66 solveL1Straight
<SL1S_B_STRIDE
>(L
, b
, rowCount
, rowSkip
);
70 doCooperativelySolveL1StraightValidated(resourceContainer
, limitedThreadCount
, L
, b
, rowCount
, rowSkip
);
76 unsigned ThreadedEquationSolverLDLT::restrictSolvingL1StraightAllowedThreadCount(
77 dxThreadingBase
*threading
, unsigned allowedThreadCount
, unsigned rowCount
)
79 unsigned limitedThreadCount
= 1;
81 #if dCOOPERATIVE_ENABLED
82 const unsigned int blockStep
= SL1S_BLOCK_SIZE
; // Required by the implementation
83 unsigned solvingBlockCount
= deriveSolvingL1StraightBlockCount(rowCount
, blockStep
);
84 dIASSERT(deriveSolvingL1StraightThreadCount(SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM
, 2) > 1);
86 if (solvingBlockCount
>= SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM
)
88 limitedThreadCount
= threading
->calculateThreadingLimitedThreadCount(allowedThreadCount
, true);
90 #endif // #if dCOOPERATIVE_ENABLED
92 return limitedThreadCount
;
96 void ThreadedEquationSolverLDLT::doEstimateCooperativeSolvingL1StraightResourceRequirementsValidated(
97 dxResourceRequirementDescriptor
*summaryRequirementsDescriptor
,
98 unsigned allowedThreadCount
, unsigned rowCount
)
100 const unsigned int blockStep
= SL1S_BLOCK_SIZE
; // Required by the implementation
101 unsigned blockCount
= deriveSolvingL1StraightBlockCount(rowCount
, blockStep
);
102 dIASSERT(blockCount
>= 1);
104 unsigned threadCountToUse
= deriveSolvingL1StraightThreadCount(blockCount
, allowedThreadCount
);
105 dIASSERT(threadCountToUse
> 1);
107 unsigned simultaneousCallCount
= 1 + (threadCountToUse
- 1);
109 SolvingL1StraightMemoryEstimates solvingMemoryEstimates
;
110 sizeint solvingMemoryRequired
= estimateCooperativelySolvingL1StraightMemoryRequirement
<blockStep
>(rowCount
, solvingMemoryEstimates
);
111 const unsigned solvingAlignmentRequired
= ALLOCATION_DEFAULT_ALIGNMENT
;
113 unsigned featureRequirement
= dxResourceRequirementDescriptor::STOCK_CALLWAIT_REQUIRED
;
114 summaryRequirementsDescriptor
->mergeAnotherDescriptorIn(solvingMemoryRequired
, solvingAlignmentRequired
, simultaneousCallCount
, featureRequirement
);
118 void ThreadedEquationSolverLDLT::doCooperativelySolveL1StraightValidated(
119 dxRequiredResourceContainer
*resourceContainer
, unsigned allowedThreadCount
,
120 const dReal
*L
, dReal
*b
, unsigned rowCount
, unsigned rowSkip
)
122 dIASSERT(allowedThreadCount
> 1);
124 const unsigned int blockStep
= SL1S_BLOCK_SIZE
; // Required by the implementation
125 unsigned blockCount
= deriveSolvingL1StraightBlockCount(rowCount
, blockStep
);
126 dIASSERT(blockCount
>= 1);
128 unsigned threadCountToUse
= deriveSolvingL1StraightThreadCount(blockCount
, allowedThreadCount
);
129 dIASSERT(threadCountToUse
> 1);
131 dCallWaitID completionWait
= resourceContainer
->getStockCallWait();
132 dAASSERT(completionWait
!= NULL
);
134 atomicord32 blockCompletionProgress
;
135 cellindexint
*blockProgressDescriptors
;
136 SolveL1StraightCellContext
*cellContexts
;
138 SolvingL1StraightMemoryEstimates solvingMemoryEstimates
;
139 sizeint solvingMemoryRequired
= estimateCooperativelySolvingL1StraightMemoryRequirement
<blockStep
>(rowCount
, solvingMemoryEstimates
);
140 dIASSERT(solvingMemoryRequired
<= resourceContainer
->getMemoryBufferSize());
142 void *bufferAllocated
= resourceContainer
->getMemoryBufferPointer();
143 dIASSERT(bufferAllocated
!= NULL
);
144 dIASSERT(dALIGN_PTR(bufferAllocated
, ALLOCATION_DEFAULT_ALIGNMENT
) == bufferAllocated
);
146 void *bufferCurrentLocation
= bufferAllocated
;
147 bufferCurrentLocation
= markCooperativelySolvingL1StraightMemoryStructuresOut(bufferCurrentLocation
, solvingMemoryEstimates
, blockProgressDescriptors
, cellContexts
);
148 dIVERIFY(bufferCurrentLocation
<= (uint8
*)bufferAllocated
+ solvingMemoryRequired
);
150 initializeCooperativelySolveL1StraightMemoryStructures
<blockStep
>(rowCount
, blockCompletionProgress
, blockProgressDescriptors
, cellContexts
);
152 dCallReleaseeID calculationFinishReleasee
;
153 SolveL1StraightWorkerContext workerContext
; // The variable must exist in the outer scope
155 workerContext
.init(L
, b
, rowCount
, rowSkip
, blockCompletionProgress
, blockProgressDescriptors
, cellContexts
);
157 dxThreadingBase
*threading
= resourceContainer
->getThreadingInstance();
158 threading
->PostThreadedCall(NULL
, &calculationFinishReleasee
, threadCountToUse
- 1, NULL
, completionWait
, &solveL1Straight_completion_callback
, NULL
, 0, "SolveL1Straight Completion");
159 threading
->PostThreadedCallsGroup(NULL
, threadCountToUse
- 1, calculationFinishReleasee
, &solveL1Straight_worker_callback
, &workerContext
, "SolveL1Straight Work");
161 participateSolvingL1Straight
<blockStep
, SL1S_B_STRIDE
>(L
, b
, rowCount
, rowSkip
, blockCompletionProgress
, blockProgressDescriptors
, cellContexts
, threadCountToUse
- 1);
163 threading
->WaitThreadedCallExclusively(NULL
, completionWait
, NULL
, "SolveL1Straight End Wait");
167 int ThreadedEquationSolverLDLT::solveL1Straight_worker_callback(void *callContext
, dcallindex_t callInstanceIndex
, dCallReleaseeID
dUNUSED(callThisReleasee
))
169 SolveL1StraightWorkerContext
*ptrContext
= (SolveL1StraightWorkerContext
*)callContext
;
171 solveL1Straight_worker(*ptrContext
, dCAST_TO_SMALLER(unsigned, callInstanceIndex
));
177 void ThreadedEquationSolverLDLT::solveL1Straight_worker(SolveL1StraightWorkerContext
&ref_context
, unsigned ownThreadIndex
)
179 const unsigned blockStep
= SL1S_BLOCK_SIZE
;
181 participateSolvingL1Straight
<blockStep
, SL1S_B_STRIDE
>(ref_context
.m_L
, ref_context
.m_b
, ref_context
.m_rowCount
, ref_context
.m_rowSkip
,
182 *ref_context
.m_ptrBlockCompletionProgress
, ref_context
.m_blockProgressDescriptors
, ref_context
.m_cellContexts
, ownThreadIndex
);
186 int ThreadedEquationSolverLDLT::solveL1Straight_completion_callback(void *dUNUSED(callContext
), dcallindex_t
dUNUSED(callInstanceIndex
), dCallReleaseeID
dUNUSED(callThisReleasee
))
193 //////////////////////////////////////////////////////////////////////////
194 // Public interface functions
197 void dSolveL1(const dReal
*L
, dReal
*B
, int n
, int lskip1
)
206 solveL1Straight
<1>(L
, B
, n
, lskip1
);
212 void dEstimateCooperativelySolveL1StraightResourceRequirements(dResourceRequirementsID requirements
,
213 unsigned maximalAllowedThreadCount
, unsigned maximalRowCount
)
215 dAASSERT(requirements
!= NULL
);
217 dxResourceRequirementDescriptor
*requirementsDescriptor
= (dxResourceRequirementDescriptor
*)requirements
;
218 ThreadedEquationSolverLDLT::estimateCooperativeSolvingL1StraightResourceRequirements(requirementsDescriptor
, maximalAllowedThreadCount
, maximalRowCount
);
222 void dCooperativelySolveL1Straight(dResourceContainerID resources
, unsigned allowedThreadCount
,
223 const dReal
*L
, dReal
*b
, unsigned rowCount
, unsigned rowSkip
)
225 dAASSERT(resources
!= NULL
);
227 dxRequiredResourceContainer
*resourceContainer
= (dxRequiredResourceContainer
*)resources
;
228 ThreadedEquationSolverLDLT::cooperativelySolveL1Straight(resourceContainer
, allowedThreadCount
, L
, b
, rowCount
, rowSkip
);