@@ -141,6 +141,72 @@ internal static void IterateRows<T, TBuffer>(
141141 rowAction . Invoke ) ;
142142 }
143143
144+ /// <summary>
145+ /// Iterate through the rows of a rectangle in optimized batches defined by <see cref="RowInterval"/>-s
146+ /// instantiating a temporary buffer for each <paramref name="body"/> invocation.
147+ /// </summary>
148+ /// <typeparam name="T">The type of row action to perform.</typeparam>
149+ /// <typeparam name="TBuffer">The type of buffer elements.</typeparam>
150+ /// <param name="rectangle">The <see cref="Rectangle"/>.</param>
151+ /// <param name="configuration">The <see cref="Configuration"/> to get the parallel settings from.</param>
152+ /// <param name="body">The method body defining the iteration logic on a single <see cref="RowInterval"/>.</param>
153+ public static void IterateRows2 < T , TBuffer > ( Rectangle rectangle , Configuration configuration , in T body )
154+ where T : struct , IRowAction < TBuffer >
155+ where TBuffer : unmanaged
156+ {
157+ var parallelSettings = ParallelExecutionSettings . FromConfiguration ( configuration ) ;
158+ IterateRows2 < T , TBuffer > ( rectangle , in parallelSettings , in body ) ;
159+ }
160+
161+ /// <summary>
162+ /// Iterate through the rows of a rectangle in optimized batches defined by <see cref="RowInterval"/>-s
163+ /// instantiating a temporary buffer for each <paramref name="body"/> invocation.
164+ /// </summary>
165+ internal static void IterateRows2 < T , TBuffer > (
166+ Rectangle rectangle ,
167+ in ParallelExecutionSettings parallelSettings ,
168+ in T body )
169+ where T : struct , IRowAction < TBuffer >
170+ where TBuffer : unmanaged
171+ {
172+ ValidateRectangle ( rectangle ) ;
173+
174+ int top = rectangle . Top ;
175+ int bottom = rectangle . Bottom ;
176+ int width = rectangle . Width ;
177+ int height = rectangle . Height ;
178+
179+ int maxSteps = DivideCeil ( width * height , parallelSettings . MinimumPixelsProcessedPerTask ) ;
180+ int numOfSteps = Math . Min ( parallelSettings . MaxDegreeOfParallelism , maxSteps ) ;
181+ MemoryAllocator allocator = parallelSettings . MemoryAllocator ;
182+
183+ // Avoid TPL overhead in this trivial case:
184+ if ( numOfSteps == 1 )
185+ {
186+ using ( IMemoryOwner < TBuffer > buffer = allocator . Allocate < TBuffer > ( width ) )
187+ {
188+ Span < TBuffer > span = buffer . Memory . Span ;
189+
190+ for ( int y = top ; y < bottom ; y ++ )
191+ {
192+ Unsafe . AsRef ( body ) . Invoke ( y , span ) ;
193+ }
194+ }
195+
196+ return ;
197+ }
198+
199+ int verticalStep = DivideCeil ( height , numOfSteps ) ;
200+ var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps } ;
201+ var rowAction = new WrappingRowAction < T , TBuffer > ( top , bottom , verticalStep , width , allocator , in body ) ;
202+
203+ Parallel . For (
204+ 0 ,
205+ numOfSteps ,
206+ parallelOptions ,
207+ rowAction . Invoke ) ;
208+ }
209+
144210 /// <summary>
145211 /// Iterate through the rows of a rectangle in optimized batches defined by <see cref="RowInterval"/>-s.
146212 /// </summary>
0 commit comments