Skip to content
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

Consider using StructLayout.Explicit for more low level optimizations #7123

Closed
dotlogix opened this issue Jun 20, 2023 · 3 comments
Closed

Comments

@dotlogix
Copy link

Describe the project you are working on

At the moment the primitive types like Vector3, Vector3I, ... all use StructLayout.Sequential.
This is fine for most use cases, but if you want to do sth a bit more low level, like SIMD vectorization or indexing with an integer it leads to problems.

The Vector struct allows to index using an integer but uses a switch internall which compared to Unsafe operations is incredibly slow (~500% slower).

Describe the problem or limitation you are having in your project

StructLayout.Sequential technically does not guarantee the order of field in managed code so using ref/reinterpret cast with vectors is not really possible. It is pretty likely they will not get realigned, but according to msdn it is not guaranteed.

I use SIMD for the performance critical part's and the slowest part of it currently is the Vector struct -> System.Numerics.Vector conversion. Using unsafe methods I could just reinterpret the struct to the other one which is a big performance boost. But as the alignment is not guaranteed it could mean I mess up my data.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

StructLayout.Explicit forces a specific order of fields so ref/reinterpret and vectorization could be a lot more performant.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

[StructLayout(LayoutKind.Explicit)]
public struct Vector3 : IEquatable
{
[FieldOffset(0)] public float X;
[FieldOffset(4)] public float Y;
[FieldOffset(8)] public float Z;
...
}

If this enhancement will not be used often, can it be worked around with a few lines of script?

Nope as alignment is not guaranteed the only viable option is copying over each field 1 by 1.

Is there a reason why this should be core and not an add-on in the asset library?

These types are primitive types in Godot so it would be benefitial for core as well for some optimizations.

@Calinou
Copy link
Member

Calinou commented Jun 20, 2023

cc @raulsntos @neikeq

@raulsntos
Copy link
Member

AFAIK the types in System.Numerics also use the Sequential layout so if you say this prevents you from using reinterpret cast I don't see how using the Explicit layout in Godot would help you. You would need the System.Numerics types to also use the Explicit layout so the field order is guaranteed in both types.

Also, according to the StructLayoutAttribute documentation:

For blittable types, LayoutKind.Sequential controls both the layout in managed memory and the layout in unmanaged memory. For non-blittable types, it controls the layout when the class or structure is marshaled to unmanaged code, but does not control the layout in managed memory.

I'm assuming this is why you believe the field order is not guaranteed. However, I think Godot's vector types should be blittable since they are formatted value types that contain only blittable types. Same as the types in System.Numerics. So you can probably assume the field order won't change.

@dotlogix
Copy link
Author

Thanks for the clarification I guess. I mainly use spans where order really matters, but you are correct missed the blittable part.
I guess I will close this then as it is not really needed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants