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

Move memory allocation out of elkan_L2_sse #280

Merged
merged 2 commits into from
Dec 27, 2023

Conversation

bjzhjing
Copy link
Contributor

@bjzhjing bjzhjing commented Dec 8, 2023

elkan_L2_sse() does malloc/free each time when it's called by the loop in train_encoded() during data train for most of IVF index building. Memory allocation triggers the process of vma allocation, physical page allocation, page mapping setup and memory cgroup statistic update in kernel side, so more frequent allocation means more overhead. Move it out of the loop and do it only once when IndexFlatElkan is initialized to save CPU cycles.

issue #279

@sre-ci-robot
Copy link
Collaborator

Welcome @bjzhjing! It looks like this is your first PR to zilliztech/knowhere 🎉

Copy link

mergify bot commented Dec 8, 2023

@bjzhjing 🔍 Important: PR Classification Needed!

For efficient project management and a seamless review process, it's essential to classify your PR correctly. Here's how:

  1. If you're fixing a bug, label it as kind/bug.
  2. For small tweaks (less than 20 lines without altering any functionality), please use kind/improvement.
  3. Significant changes that don't modify existing functionalities should be tagged as kind/enhancement.
  4. Adjusting APIs or changing functionality? Go with kind/feature.

For any PR outside the kind/improvement category, ensure you link to the associated issue using the format: “issue: #”.

Thanks for your efforts and contribution to the community!.

@liliu-z
Copy link
Collaborator

liliu-z commented Dec 8, 2023

Thanks for this PR, we will take a look ASAP.

@liliu-z
Copy link
Collaborator

liliu-z commented Dec 8, 2023

/assign @alexanderguzhva
Hi Alex, do you mind to take a check? Thanks!

@liliu-z
Copy link
Collaborator

liliu-z commented Dec 8, 2023

/kind enhancement

@@ -422,6 +422,7 @@ void compute_PQ_dis_tables_dsub2(
* @param y database vectors, size ny * d
* @param ids result array ids
* @param val result array value
* @param data the pointer of memory for symmetric matrix data
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please call this variable tmp_buffer in order to stress out its meaning. It is not a data, it is a temporary storage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for helping review, Alex! The change is done.


namespace faiss {

IndexFlatElkan::IndexFlatElkan(idx_t d, MetricType metric, bool is_cosine, bool use_elkan)
IndexFlatElkan::IndexFlatElkan(idx_t d, MetricType metric, bool is_cosine, bool use_elkan, float* data)
Copy link
Collaborator

Choose a reason for hiding this comment

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

?! data which is passed as a parameters is not used anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it's not required to be set by callers. Remove it from the interface.

@@ -29,9 +29,17 @@ namespace faiss {
// Elkan algo was introduced into Knowhere in #2178, #2180 and #2258.
struct IndexFlatElkan : IndexFlat {
bool use_elkan = true;
float* data = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

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

std::vector<float> tmp_buffer_for_elkan;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed it.

thirdparty/faiss/faiss/IndexFlatElkan.h Outdated Show resolved Hide resolved
if (nx == 0 || ny == 0) {
return;
}

const size_t bs_y = 1024;
float* data = (float*)malloc((bs_y * (bs_y - 1) / 2) * sizeof(float));
bool allocate = false;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use std::unique_ptr<float[]> + new for allocating a local temporary buffer

Copy link
Contributor Author

@bjzhjing bjzhjing Dec 9, 2023

Choose a reason for hiding this comment

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

Call std::make_unique<float[]>() to allocate memory for tmp_buffer in IndexFlatElkan constructor. Remove the checking from elkan_L2_sse() for use_elkan can help ensure the memory is allocated when come there.

@bjzhjing
Copy link
Contributor Author

@alexanderguzhva Hi Alex, I use smart pointer instead of std::vector to implement the tmp_buffer finally, for I IndexFlatElkan::search is defined with 'const', which means it's not allowed to modify the class variables. Thus, it's required to use const_cast<std::vector&> for convert while passing tmp_buffer to elkan_L2_sse, there is address change, which make things a bit complex. Smart pointer can help avoid the issue and make the code more clean and safe.

Please help review. Thanks very much!

@mergify mergify bot added the ci-passed label Dec 14, 2023
@alexanderguzhva
Copy link
Collaborator

@bjzhjing Two more notes

  1. Please add a comment about the situation to the top of IndexFlatElkan . Basically, in the provided form IndexFlatElkan is no longer thread-safe for the search. So, two threads cannot use 'IndexFlatElkan::search()' simultaneosly on the same instance. This is fine, bcz IndexFlatElkan is used only during the index construction. But the note about the implementation detail and why this was done should be included.
  2. The needed size of the temporary buffer depends on the const size_t bs_y = 1024; magic constant inside elkan_L2_sse(). So, notes on the sizes need to be added to the description of the elkan_L2_sse() implementation. Maybe, bs_y size needs to be exposed as a function parameter as well.

elkan_L2_sse() does malloc/free each time when it's called by the loop
in train_encoded() during data train for most of IVF index building.
Memory allocation triggers the process of vma allocation, physical page
allocation, page mapping setup and memory cgroup statistic update in
kernel side, so more frequent allocation means more overhead. Move it
out of the loop and do it only once when IndexFlatElkan is initialized
to save CPU cycles.

Signed-off-by: Cathy Zhang <cathy.zhang@intel.com>
For the memory allocation is moved to IndexFlatElkan construction,
replace bs_y with the parameter defined and passed by Index.

Signed-off-by: Cathy Zhang <cathy.zhang@intel.com>
@bjzhjing
Copy link
Contributor Author

@bjzhjing Two more notes

  1. Please add a comment about the situation to the top of IndexFlatElkan . Basically, in the provided form IndexFlatElkan is no longer thread-safe for the search. So, two threads cannot use 'IndexFlatElkan::search()' simultaneosly on the same instance. This is fine, bcz IndexFlatElkan is used only during the index construction. But the note about the implementation detail and why this was done should be included.
  2. The needed size of the temporary buffer depends on the const size_t bs_y = 1024; magic constant inside elkan_L2_sse(). So, notes on the sizes need to be added to the description of the elkan_L2_sse() implementation. Maybe, bs_y size needs to be exposed as a function parameter as well.

Greetings @alexanderguzhva! I'm just back from a bad cold, and sorry for the late response. I've addressed your above comments. Please help review, thanks!

@PwzXxm
Copy link
Collaborator

PwzXxm commented Dec 27, 2023

/lgtm
/approve

@sre-ci-robot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bjzhjing, PwzXxm

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@mergify mergify bot added the ci-passed label Dec 27, 2023
@sre-ci-robot sre-ci-robot merged commit 2a7848a into zilliztech:main Dec 27, 2023
9 checks passed
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.

5 participants