-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Analysis re-reworking #34
Analysis re-reworking #34
Conversation
Keeping this in means we will need to keep it updated with the equivalent methods in the component, which is unnecessary churn. Better to use these methods adhoc and not in git
…loses mariuszhermansdorfer#29 This includes earlier optimisations that were not present (e.g. the color table as a dictionary) and reworks the way analysis is applied so that mariuszhermansdorfer#33 can be implemented. Future tweaks will be benchmarked and sent in PRs
…r levels; contours) + split up Analysis.cs Analysis.cs was getting a little large; the new file contains just the implementations of each analysis option
SandWorm/Analytics.cs
Outdated
for (int i = 0; i < neighbours.Count; i++) | ||
{ | ||
double rise = vertex.Z - neighbours[i].Z; | ||
double run = Math.Sqrt(Math.Pow(vertex.X - neighbours[i].X, 2) + Math.Pow(vertex.Y - neighbours[i].Y, 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are going with the D4 approach, half of this equation is always going to be zero. In the N-S direction, deltaX = 0, for E-W, deltaY = 0.
I think this whole line could then be reduced to a simple subtraction. Especially given, that you are checking whether the neighbors exist in the main component anyway.
if (i >= trimmedWidth)
neighbourPixels.Add(pointCloud[i - trimmedWidth]); // North neighbour
if ((i + 1) % (trimmedWidth) != 0)
neighbourPixels.Add(pointCloud[i + 1]); // East neighbour
if (i < trimmedWidth * (trimmedHeight - 1))
neighbourPixels.Add(pointCloud[i + trimmedWidth]); // South neighbour
if (i % trimmedWidth != 0)
neighbourPixels.Add(pointCloud[i - 1]); // West neighbour
Looking forward to seeing this implemented! Maybe @Sergio0694 has some ideas on how to approach this. |
Hey @mariuszhermansdorfer - I'd be happy to help but I'm not 100% sure about what you're trying to do here. A couple small tweaks right off the bat, from what I'm seeing:
Other than that, what kind of effect are you trying to apply here? If it's a 2D convolution with some kernel that is linearly separable, then yeah you can replicate my gaussian blur effect by using two 1D convolutions instead of one. This of course gets the computation cost down from |
Thanks @Sergio0694! Sorry for not providing a clearer explanation of what we are trying to accomplish. The goal is to visualize slope of the terrains created in the sandbox. To achieve that, we need to calculate a value for each pixel and store it in an array. This is then passed to our meshing function as vertexColors information. Does this sound like a good candidate for linear separation? |
I'm sorry, I still don't really understand the exact operation you're describing.
Anyway, if the total area being processed for a single pixel is just the 3x3 square centered in that pixel, even if you could come up with a linearly separable kernel to represent that operation it likely wouldn't bring a performance increase, as the kernel is so small already.
As for point 2, as an example: imagine that for each pixel you were just summing its value and the one of the 2 following pixels, if within bounds (completely made up example, bear with me). Classic implementation (with no optimizations): const int width = 640, height = 380;
int[] image = new int[width * height];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int sum = 0;
for (int i = 0; i < 3; i++)
{
if (x + i == width) break;
sum += image[y * width + x + i];
}
image[y * width + x] = sum;
}
} Unrolled implementation (with no other optimizations): for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int sum = image[y * width + x];
if (x + 1 < width) sum += image[y * width + x + 1];
if (x + 2 < width) sum += image[y * width + x + 2];
image[y * width + x] = sum;
}
} Note though that the second is more of a micro-optimization, so I'd suggest to just making the code run in parallel, that might very well be enough for you already. Following up from the previous example, the parallelized version could look something like this: Parallel.For(0, height, y =>
{
for (int x = 0; x < width; x++)
{
int sum = image[y * width + x];
if (x + 1 < width) sum += image[y * width + x + 1];
if (x + 2 < width) sum += image[y * width + x + 2];
image[y * width + x] = sum;
}
}); Hope this helps! P.S.: bonus example if you really want to squeeze out as much performance as possible: Parallel.For(0, height, y =>
{
ref int row = ref image[y * width];
for (int x = 0; x < width; x++)
{
int sum = 0;
if (x + 1 < width) sum += Unsafe.Add(ref row, x + 1);
if (x + 2 < width) sum += Unsafe.Add(ref row, x + 2);
Unsafe.Add(ref row, x) += sum;
}
}); But again, first just make the code run in parallel 👍 |
Thanks, @Sergio0694! To answer your questions:
Following your suggestion I wrote a very verbose slopeCalculator. It first takes care of the edge cases for individual pixels in the corners of the image (NW, NE, SW, SE), rows (first and last) and columns (first and last) and then iterates over the main array. Results are pretty satisfying, but also quite surprising. Sequential for loop - 2ms Parallel for loop - 14 ms I suspect it is because the logic needs to read pixel values from other rows which may be locked by other threads writing to it. Any ideas on how to optimize it from there? Maybe some of your |
@mariuszhermansdorfer So, by quickly looking at your code, a few suggestions come to mind:
// Replace this
ushort[] slopeValues = new ushort[width * height];
// With this
ushort[] slopeValues = ArrayPool<ushort>.Shared.Rent(width * height);
After you're done with all of these I might also do a pass replacing those array accesses with Hope this helps! |
@Sergio0694, you're awesome! Point number 4 made an enormous difference! Localizing the variable took it down to less than 1 ms. Most satisfying :) I will implement the rest of your suggestions tomorrow to make it even snappier. I have two questions, though:
|
@mariuszhermansdorfer Ahahah thanks, happy to help! 😊 As for your questions:
// Somewhere in your code when you need this
var slopes = SlopeCalculator.CalculateSlope(...);
// Do stuff with slopes...
ArrayPool<double>.Shared.Return(slopes); That is, return that array when you're sure you won't be using it again. For instance, if you're getting that array within some other method, which is using it to do some other work and then just discarding it (ie. not returning it or saving it somewhere else), you could just return that array to the pool at the end of that method. |
aa743e8
to
f40393f
Compare
Thanks also for your help @Sergio0694! I think we are stuck on .NET 4.5 as this is what our host environment provides, although it is worth testing if we can get around that. @mariuszhermansdorfer the new We have a few different branches floating around that should probably be resolved first before pursuing that option. Is it OK to merge this branch in? I can then merge/integrate the new setup component, and then rework the analysis classes to integrate the method from |
@philipbelesky, yes, please go ahead with the merging. I wasn't pushing any other commits to the master just to make sure I don't make your life harder with integrating the analysis part. |
Thanks for clarifying things, @Sergio0694. As far as I can understand, we are stuck with .NET 4.5 unless we explicitly make our users install newer versions of the framework. I must admit, I don't understand this explanation fully, but it seems we can't use the .NET Core for this particular project. |
# Conflicts: # SandWorm/Analysis.cs # SandWorm/SandWormComponent.cs
No problem! As for .NET Core 3.0, if these changes have already brought the time it takes to perform this section of the pipeline down to below 1ms I'd say you can just forget about that then. |
7bfca33
to
f350e64
Compare
Is this one ready to be merged into master @philipbelesky? Feel free to do it when you think we're good to go. |
Great, done. I’ll have some time later this week to integrate the new structure of the slope algorithm and will try to replicate it for aspect at the same time. |
Hey, this is just a tracking PR for some of the ongoing changes that cut across #30 #33 #13; will post highlights as I go and signal when a full review is ready. As of now:
MeshGeometryAnalysis
class of analyses to output geometry after the point cloud/mesh items have been made; e.g. for the water plane or contouring.