Notifications
Clear all

[Closed] .net sdk memory management problem

after optimization the loop should look as (IMHO):

		  for (int i = 0; i < numMapVerts; i++)
		  {
			  IPoint3 vertex = mesh.GetVert(i);
  
			  mapVerts[i].X = 1; // if you need to double-check it
			
			if (vertex.Z > HeightThreshold)
			  {
				  mapVerts[i].Y = Math.Max(0, mapVerts[i].Y - FadeInValue);
				  //mapVerts[i].Z = Math.Max(0, mapVerts[i].Z - FadeInValue);  // if it's not a grey scale
			  }
			  else 
			{
				  mapVerts[i].Y = Math.Min(1, mapVerts[i].Y + FadeInValue);
				  //mapVerts[i].Z = Math.Min(1, mapVerts[i].Z + FadeInValue);  // if it's not a grey scale
			  }
			mapVerts[i].Z = mapVerts[i].Y; // if it's a grey scale
		  }

i believe we can do color assignment in place. and after compilation Math.Min or Math.Max is exactly the same as one comparison and one assignment.

1 Reply
(@polytools3d)
Joined: 11 months ago

Posts: 0

This runs over 2 times slower on my tests.

I suppose this is due to the constant access to the mapVerts List (mapVerts[i].X, mapVerts[i].Y, mapVerts[i].Z) instead of writing the value back at once as I did in the latest function.

 lo1

Are you compiling with optimizations enabled?

1 Reply
(@polytools3d)
Joined: 11 months ago

Posts: 0

Yes… I think :).
Are you getting different results? I mean for comparison with Denis’s code on #28 I get around 2.2 slowdown. Is that what you are talking about?

 lo1

I haven’t tried compiling, just thought it would explain why you get such different performance.

1 Reply
(@polytools3d)
Joined: 11 months ago

Posts: 0

Would you try both functions if you get some time?
It would be great to have your opinion and findings.

I’ll test all these potential optimizations when I get back home from work. I appreciate all the tips so far!

Yeah, it works pretty well with just the height criterion. Here is a test the guy I helped made:

//youtu.be/iw0t_W_k7XA

slowing down for in-place method doesn’t make sense for me. probably it’s some issue specific to max .net sdk.
if removing unnecessary multiplications and divisions don’t really affect the performance that means 99% of time the method is doing something different. but i don’t see anything unless taking a value from one piece of memory and putting to another. in c++ sdk it’s almost nothing and doesn’t take any time.

2 Replies
 lo1
(@lo1)
Joined: 11 months ago

Posts: 0

I tried both versions and I get same result as PolyTools3D – the in-place version is about 60% slower for me.

I believe this is because that no value data is actually stored on the IPoint3:

bFlags = (dotnetClass "System.Reflection.BindingFlags")
allFields = dotnet.CombineEnums bFlags.Public bFlags.NonPublic bFlags.Instance
fields = ((((dotnetclass "Autodesk.Max.GlobalInterface").Instance.Point3.Create 1 1 1).GetType()).GetFields allFields)
for p in fields do print (p.ToString())

"Point3* unmanaged_"
"Boolean owning_"

The only data is a pointer to a native Point3. Each access requires dereferencing a native pointer, which I assume is slower from a c# assembly.

Nevertheless, the method runs very fast (1-2 ms for 40000 vertices on my machine), and if you need it any faster than this, you might as well start over in C++.

(@polytools3d)
Joined: 11 months ago

Posts: 0

The C# takes 3ms to process a 100K mesh (3000ms for 1000 calls)

How much is “almost nothing” in C++? Just curious to know how much faster is the native code.

 lo1

This runs about 18 times faster (yes, this is still c# code )


//define this somewhere in your class
   struct Point3
        {
            public float X;
            public float Y;
            public float Z;
        }


Point3* mapP = (Point3*)(mapVerts[0] as Autodesk.Max.Wrappers.Point3).INativeObject__Handle;
Point3* meshP = (Point3*)(mesh.GetVert(0) as Autodesk.Max.Wrappers.Point3).INativeObject__Handle;

for (int i = 0; i < numMapVerts; i++)
{
    mapP->X = 1;
    if (meshP->Z > HeightThreshold)
    {
        mapP->Y = Math.Max(0, mapP->Y - FadeInValue);
    }
    else
    {
        mapP->Y = Math.Min(1, mapP->Y + FadeInValue);
    }
    mapP->Z = mapP->Y;
    mapP++;
    meshP++;
}

for 1000 iterations:
previous fastest version: ~1800ms
this version: ~100ms

It requires you to reference Autodesk.Max.Wrappers in your project, and compile with unsafe code flag.

I wouldn’t recommend doing this in production code, I don’t know what issues could occur.

Great! 0.00016 seconds to process a 100K mesh isn’t bad, or is it?

 lo1

This would still be faster in C++, especially if it is SIMDed.

this is almost the same what c++ code has to do. excepting that mesh verts and map verts are already arrays of Point3.

i don’t think c++ code can do it much faster. only maybe getting the mesh might be a little faster.
another thing is update the render mesh after you set this colors and force rebuild of a cached one. and i’m not sure it’s possible to rebuild only colors. so the update will take much more time than a calculation.

1 Reply
(@polytools3d)
Joined: 11 months ago

Posts: 0

I was actually expecting the C++ version to be 3-5 times faster, but 20 times faster is still a huge difference.

Although this function involves very common operations, I supposed the difference can be much larger than that in other cases.

Well, I guess a more flexible language comes with its price. What a shame that we can’t maintain and compile a single C++ version.

Thank you Rotem and Denis for your input, and thank you Håvard for sharing this.

Page 3 / 4