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

chore(allocator): make and makeArray should allocate aligned memory #8577

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ljmf00
Copy link
Member

@ljmf00 ljmf00 commented Sep 19, 2022

Signed-off-by: Luís Ferreira [email protected]

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @ljmf00!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + phobos#8577"

@ljmf00
Copy link
Member Author

ljmf00 commented Sep 19, 2022

Humm, why does RCIAllocator skip zeroed allocation method, but not aligned allocation, that is also optional? I think this is still badly designed, unfortunately. A generic allocator may only assume methods that are required to be implemented on every allocator, otherwise we rely on special return values that are both used for errors on allocation and not implemented.

Copy link
Collaborator

@RazvanN7 RazvanN7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this? If make/makeArray is instantiated with AlignedMallocator then all of this becomes moot.

I get the impression that make/makeArray is supposed to simply use the allocate method of the allocator that is being passed to it.

@ljmf00
Copy link
Member Author

ljmf00 commented Oct 5, 2022

Do we really need this? If make/makeArray is instantiated with AlignedMallocator then all of this becomes moot.

Yes, to improve correctness. I would expect correct alignment when providing AlignedMallocator to makeArray.

@atilaneves
Copy link
Contributor

Do we really need this? If make/makeArray is instantiated with AlignedMallocator then all of this becomes moot.

Yes, to improve correctness. I would expect correct alignment when providing AlignedMallocator to makeArray.

Does that not happen now?

@ljmf00
Copy link
Member Author

ljmf00 commented Oct 5, 2022

Do we really need this? If make/makeArray is instantiated with AlignedMallocator then all of this becomes moot.

Yes, to improve correctness. I would expect correct alignment when providing AlignedMallocator to makeArray.

Does that not happen now?

No. That's what this PR is trying to solve, although, the design of the allocators doesn't allow doing it efficiently. It requires checking for null on Allocators wrapped in an interface.

See:

struct S
{
align(512):
    int a;
    float b;
    int c;
}

S* s1 = new S();
assert(cast(size_t)s1 % 512 == 0, "Misaligned"); // fine
S* s2 = AlignedMallocator.instance.make!S();
assert(cast(size_t)s2 % 512 == 0, "Misaligned"); // triggers

@RazvanN7
Copy link
Collaborator

RazvanN7 commented Oct 6, 2022

@ljmf00 This seems to be a problem of AlignedMallocator. It seems that the alignment is hardcoded to be the platform alignment. I think that AlignedMallocator should just have an instance dependent alignment. Of course, that does not bode well with the current pattern of using a static shared instance of it. Is there anything preventing us from allowing AlignedMallocator from being used from different, independent instances that have their own alignment? I think that this is a more general solution compared to the one in this PR.

@ljmf00
Copy link
Member Author

ljmf00 commented Oct 6, 2022

@ljmf00 This seems to be a problem of AlignedMallocator. It seems that the alignment is hardcoded to be the platform alignment. I think that AlignedMallocator should just have an instance dependent alignment. Of course, that does not bode well with the current pattern of using a static shared instance of it. Is there anything preventing us from allowing AlignedMallocator from being used from different, independent instances that have their own alignment? I think that this is a more general solution compared to the one in this PR.

Why are you required to create new allocators for each alignment sizes? I'm not getting your suggestion. Maybe you can ellaborate, but from my understanding that is not the intended way.

There's a defined optional function that an allocator can define called alignedAllocate that provides that capability.

The alignment property you mentioned is to describe the alignment of memory allocated with allocate function. It is hardcoded because it uses an underlying malloc for normal "unaligned" allocations (provided by allocate method), which defaults to platform alignment.

The fact that the generic allocator wrapper, provides a alignedAllocate, is, in my opinion wrong design. Now, to support this correctly and/or efficient, we need to either check for null or add special cases.

IMO, a generic allocator should only provide strictly mandatory functions to be implemented by any allocator. With the current behavior, no one is going to use alignedAllocate in performant code, because apart from calling a virtual function, it might yield null at runtime and you have to do additional branching to do the fallback correctly. As much as possible, the existence of this method should be checked or encouraged to be checked at compile-time.

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

Successfully merging this pull request may close these issues.

6 participants