Skip to content

add Coarse Memory Provider #378

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

Closed

Conversation

bratpiorka
Copy link
Contributor

@bratpiorka bratpiorka commented Mar 22, 2024

Description

This PR adds the Coarse Memory Provider that could be used as a cache for upstream providers (like Level Zero Memory Provider) or handle user-provided buffers e.g. allocated using mmap.

Checklist

  • Code compiles without errors locally
  • All tests pass locally
  • CI workflows execute properly
  • CI workflows, not executed per PR (e.g. Nightly), execute properly
  • New tests added, especially if they will fail without my changes
  • Added/extended example(s) to cover this functionality
  • Extended the README/documentation
  • All newly added source files have a license
  • All newly added source files are referenced in CMake files
  • Logger (with debug/info/... messages) is used

@bratpiorka bratpiorka force-pushed the rrudnick_coarse_provieder branch from 78435f3 to 90b2547 Compare March 22, 2024 10:09
Copy link
Member

@igchor igchor left a comment

Choose a reason for hiding this comment

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

I haven't looked at the provider implementation yet but regarding tests, I think it would be good to:

  • add some multithreaded tests
  • add asan/memcheck annotations to coarse provider ( and enable them at least when we're testing coarse-provider directly)

umf_ba_global_free(coarse_provider);
}

static umf_result_t coarse_memory_provider_alloc(void *provider, size_t size,
Copy link
Member

Choose a reason for hiding this comment

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

this function is too long, please split it into multiple function

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed in #715

return block;
}

static bool debug_check(coarse_memory_provider_t *provider) {
Copy link
Member

Choose a reason for hiding this comment

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

please split this into multiple checks/functions

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed in #715

size_t max_alloc_size = 0;

// s1
for (int j = 0; j < 2; j++) {
Copy link
Member

Choose a reason for hiding this comment

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

magic values: 2, 6, please use some consts

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed in #715

umf_result_t ret = umfPoolFree(pool, ptr);
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);

allocs.erase((*it));
Copy link
Member

Choose a reason for hiding this comment

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

erase(it) would probably be faster

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed in #715

return "malloc";
}

struct umf_memory_provider_ops_t UMF_MALLOC_MEMORY_PROVIDER_OPS = {
Copy link
Member

Choose a reason for hiding this comment

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

You don't have to implement this provider - we already have one: https://github.com/oneapi-src/unified-memory-framework/blob/main/test/common/provider.hpp#L113

If you need to customize the provider_malloc you can also just create a struct that inherits from provider_base_t and overrides the functions that you need.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed in #715

std::uniform_real_distribution<float> actions_dist(0, 1);

std::set<alloc_ptr_size> allocs;
for (size_t i = 0; i < 100; i++) {
Copy link
Member

Choose a reason for hiding this comment

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

This whole loop could be simplified (and made more readable) if you'd implement the logic for choosing size/action, etc. in a separate function/class:

allocation_state state; // holds std::set<alloc_ptr_size>
for (size_t i = 0; i < 100; i++) {
   auto action = generator.get_action();
   if (action.is_alloc()) {
       state.do_alloc(action.count, ...);
   } else {
       state.do_free(action.acount, ...);
   }
}

Copy link
Member

Choose a reason for hiding this comment

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

Also, this way you could reuse this for other tests (even multithreaded perhaps)


const unsigned char alloc_check_val = 11;
coarse_memory_provider_params_t coarse_memory_provider_params = {
NULL, // upstream_memory_provider
Copy link
Member

Choose a reason for hiding this comment

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

Can't you just set each field separately as you do with disjoint_pool_params below instead of using comments?

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed in #715

const size_t init_buffer_size = 200 * MB;

// Preallocate some memory
void *buf = malloc(init_buffer_size);
Copy link
Member

Choose a reason for hiding this comment

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

Please avoid raw allocations in C++ and use unique_ptr or a container (e.g. vector or string). If this test is run under valgrind and some assert triggers or an exception is thrown buf will not be freed and valgrind will report a memory leak (which makes it harder to debug).

Copy link
Member

Choose a reason for hiding this comment

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

Ideally we would use unique_ptr for pools and providers as well but that would require more refactoring I guess.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed in #715

@bratpiorka bratpiorka force-pushed the rrudnick_coarse_provieder branch 2 times, most recently from a0d1606 to 8e578e6 Compare March 26, 2024 10:46
@lplewa
Copy link
Contributor

lplewa commented Mar 27, 2024

This PR is huuuuugeeeee. also it seems there is a lot small random fixes which do not belong to this change.

To make reviewer life easier please:

  • Split small fixes to separate commits and PRs. (things like typos, small refactoring etc)
  • Try to split this PR to smaller one (i.e Ravl can be added in separate PR with a few tests to prof it's working)

Also having more smaller self-contained commits, helps in case of debuging/bisecting,

igchor and others added 2 commits April 25, 2024 17:41
So that users of umf pools (which are static libraries)
do not have to link with umf_utils themselves.

It's not possible to link static libraries to other
static libraries.
@bratpiorka bratpiorka force-pushed the rrudnick_coarse_provieder branch from 8e578e6 to f9b4dff Compare April 25, 2024 15:44
This was referenced Sep 6, 2024
@lplewa lplewa closed this Sep 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants