Indeed. It is the setlengths in loops that bites you. Never do that for performance code.
...
The second one is the lazy copy mechanism. Arrays are reference counted to minimize copy operations. But when you change the array it needs to be copied. So on every single write access, code is executed that checks if the reference counter is 1 and if it is greater, it will copy the array into a new memory location before performing the access
...
...
To avoid this, you can use pointer access to the array:
var MyArray: Array of Single; begin SetLength(MyArray, 2); PSingle(MyArray)[0] := 42; PSingle(MyArray)[1] := 3.14159; end;
Can anyone suggest modifications to the code that can improve dynamic array performance.For me
Blur time 2618With replace (commented out) in blurSd
Blur time (dynamic arrays) 2582
i tried test program on my slightly ol PC and got different results 3 times:
PSingle: 3496
Index: 3873
PSingle: 3834
Index: 3511
PSingle: 3562
Index: 3594
i think, it shows not too good test algorithm
The attached project computes a gaussian blur on a 3D volume of dimensions kDim^3. With kDim = 256, the exact same computations are 172 times slower (Apple M1, 1394 vs 239723 ms) and 294 times slower (Ryzen 3900X, 2706 vs 796013 ms ) than using traditional arrays. I realize that there is some overhead to calling setlength(), where the array will be initialized as zeros, but there are very few calls to setlengths().In case of a dynamic array, there's (on 64 bit platforms) a 16 byte header at the start of the memory block (containing the reference count and size), but I'm not sure how that could explain such a difference in speed.
[…] I have used dynamic arrays extensively in my projects as they are convenient. […]Dynamic arrays are managed data types (https://www.freepascal.org/docs-html/ref/refse20.html). The FPC will automagically insert try … finally frames when you use them. You can [but shouldn’t] control this with {$implicitExceptions} (https://www.freepascal.org/docs-html/current/prog/progsu34.html). For more on that topic cf. avoiding implicit try finally section (https://wiki.freepascal.org/Avoiding_implicit_try_finally_section) in the Wiki.
ASergecopy always allocates a new array.
I agree that the difference in speed can be resolved by changing the dynamic array call from
tmp := copy(img, imgp, nx);
to
Move(img^[imgp], tmp^[0], nx * 4);
Even though the array has the same size before and after the copy(), there seems to be a big penalty.
I agree that the difference in speed can be resolved by changing the dynamic array call fromAgain, you did not understand me. The problem is that the functions with a dynamic and static array are different. That is, they do not the same thing. That is, it is useless to compare them, no matter what tricks you do with Move. They are different!
tmp := copy(img, imgp, nx);
to
Move(img^[imgp], tmp^[0], nx * 4);
By the way, how do I set a thread to being "solved" with this forum?