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

Modify ggml_backend_is_cpu to use ggml_backend_i::get_name callback #741

Closed
wants to merge 2 commits into from

Conversation

uextm
Copy link
Contributor

@uextm uextm commented Feb 21, 2024

This function was not actually calling the callback.

Instead, it was comparing the callback function to the static CPU name function. This does not work for sharing backends between modules in multi module programs.

This function was not actually calling the callback.

Instead, it was comparing the callback function to the static CPU name function. This does not work for sharing backends between modules in multi module programs.
@uextm
Copy link
Contributor Author

uextm commented Feb 21, 2024

Another thing to consider, would an int or enum value be better than a name to avoid a string comparison?

I only modified it to use the existing functions.

@slaren
Copy link
Collaborator

slaren commented Feb 21, 2024

Can you elaborate on why you need this change? How are you trying to use ggml?

@uextm
Copy link
Contributor Author

uextm commented Feb 21, 2024

@slaren The better question is why was the original code comparing function pointers? This logic should be changed simply because it doesn't even use the callback properly.

Here is an actual scenario that cause an issue to explain why this needs to change:

  1. You have a multi-module program.
  2. In one module you create a llama.cpp context.
  3. In another module you use that llama.cpp context to call llama_decode
  4. llama_decode calls ggml_backend_is_cpu which returns false, because backend->iface.get_name == ggml_backend_cpu_name is false due to backend->iface.get_name and ggml_backend_cpu_name belonging to different modules

I'm surprised you're asking me to elaborate on why this change is needed when it's clear that the comparison in the code is just plain the incorrect comparison to make.

@slaren
Copy link
Collaborator

slaren commented Feb 21, 2024

The original code is comparing function pointers because backend names are not meant to be unique identifiers. What you are doing is linking multiple times to ggml, and then using objects created with one copy in a different copy. That's not a supported scenario. You could try using a dynamic build of ggml instead, but in any case, this is not a good way to address this problem.

@uextm
Copy link
Contributor Author

uextm commented Feb 21, 2024

@slaren It works just fine using multiple modules. This is the only issue that stops it from working correctly.

The original code is comparing function pointers because backend names are not meant to be unique identifiers

Please explain why the function get_name returns any values at all if it will never be called and you're just going to compare its function pointer.

this is not a good way to address this problem
I agree this is not the best solution to the problem but I was attempting to make minimal changes.

This comparison should have been comparing an enum and it shouldn't be called a "backend name" since it isn't treated as one.

The only thing that absolutely shouldn't be the solution is comparing function pointers.

@slaren
Copy link
Collaborator

slaren commented Feb 21, 2024

Backend names are meant to be informative strings that can be shown to the user. They were never meant to be used as unique identifiers. This wouldn't work with multi GPU backends that assign different names depending on the device being used, for example. Adding an enum is not an option because there isn't a fixed list of backends.

In any case, I think that you can address this by linking dynamically to ggml, and using a single copy of the binary. This will also save you some memory.

@slaren slaren closed this Feb 21, 2024
@uextm
Copy link
Contributor Author

uextm commented Feb 21, 2024

@slaren I think you misunderstood what I was trying to say.

Right now backend names aren't being used except in this function to check if the backend is CPU.

I understand if get_name is intended to be used by others to get a display name, but it shouldn't be the basis for this logic.

I'm suggesting that the logic for determining the value of ggml_backend_is_cpu should be based on a boolean/integer/enum that has nothing to do with get_name.

Conflating the purpose of get_name as a function for getting a user displayable string and using its pointer for determining if a given backend is CPU makes the function unclear at the very least.

@slaren
Copy link
Collaborator

slaren commented Feb 21, 2024

The reason the get_name function is used in the ggml_backend_is_xxx functions is just because it was a simple way to implement these functions in the absence of other unique identifiers. It could be any other function in the ggml-backend interface, get_name just happens to be the first one so I choose to use that one. That does not mean that the get_name function is meant to be used in this way.

We cannot really have an enum because I don't want to have a centralized list of backends - users should be able to add their own backends without having to modify the ggml source code. What we could do instead is use a GUID to identify the backends, and add it to the ggml_backend struct. If you are willing to implement that, that could be merged.

In the future, the plan is to make the backends dynamic libraries that can be loaded at runtime. This will also require changes to the way backend-specific functions are currently implemented, including the ggml_backend_is_xxx functions. At that time I plan to re-evaluate this.

@uextm
Copy link
Contributor Author

uextm commented Feb 21, 2024

@slaren
The way I was thinking about it at least, an enum doesn't need to be an exhaustive list.
It could simply be CPU / Other which is more expandable in the future than a boolean and is more descriptive than a naked integer.

I am not against the GUID solution either and I can implement that if you'd like.
Would you want this done via a getter in ggml_backend_i or as a member of ggml_backend? (or a different method)

@slaren
Copy link
Collaborator

slaren commented Feb 21, 2024

Since this is a constant, I think it would be fine to add this directly to the ggml_backend struct instead of adding a getter in the ggml_backend_i interface. We would also need to backend-specific global functions to obtain the GUID of each backend, akin to the current ggml_backend_is_xxx functions.

@uextm uextm deleted the patch-1 branch February 21, 2024 23:56
@uextm
Copy link
Contributor Author

uextm commented Feb 22, 2024

@slaren

For the GUID implementation do you want me to use platform UUID providers (meaning a wrapper for the Windows/Linux/MacOS/iOS/Android calls and value buffer) ?

Or did you want something much simpler that just used a sequence or random ID generated completely within ggml?

I'm asking because of the "No third-party dependencies" goal.
I also saw llama.cpp had this listed even though it depends on ggml, so I'm a bit unclear on what counts as "third-party".

@uextm
Copy link
Contributor Author

uextm commented Feb 22, 2024

Also should it be in a separate header/c pair (ggml-guid.h / ggml-guid.c)?

This way the GUID implementation could be used by other non-backend specific things (unsure if wanted/needed).

@slaren
Copy link
Collaborator

slaren commented Feb 22, 2024

I don't think that we need to generate UUIDs, they can be generated with externals tools and be pre-defined for each backend. The only goal here is to avoid accidental collisions. So basically all that we need is a 128-bit UUID, in a standard format so that we can use existing tools to generate them, and a function to compare them.

@uextm
Copy link
Contributor Author

uextm commented Feb 22, 2024

What about generating the UUID for the CPU backend?

Shouldn't that be set when the backend is initialized in ggml_backend_cpu_init?

@slaren
Copy link
Collaborator

slaren commented Feb 22, 2024

Yes, but it doesn't need to be generated on the fly, it can a constant pre-defined in the code. Just keep the GUID of each backend in a global, or in as a static in the function that returns it, and set it in ggml_backend struct in the backend init functions.

@uextm
Copy link
Contributor Author

uextm commented Feb 22, 2024

What value do you want to use as the pre-defined constant for the CPU backend GUID?

@slaren
Copy link
Collaborator

slaren commented Feb 22, 2024

It can be any random value. For example I just found this site: https://www.uuidgenerator.net/. From what I understand, UUID v4 are just 128-bit completely random number without any real structure (other than the version I guess).

@uextm
Copy link
Contributor Author

uextm commented Feb 22, 2024

I'm aware it can be any value, I'm asking for your preference since you're the maintainer.

If you're fine with any random value than I'll do that.

uextm added a commit to uextm/ggml that referenced this pull request Feb 22, 2024
Initial proposed implementation of backend GUIDs
(Discussed in ggerganov#741)

Hardcoded CPU backend GUID (for now)
Change ggml_backend_is_cpu logic to use GUID
@uextm uextm mentioned this pull request Feb 22, 2024
slaren added a commit that referenced this pull request Feb 24, 2024
* Introduce backend GUIDs

Initial proposed implementation of backend GUIDs
(Discussed in #741)

Hardcoded CPU backend GUID (for now)
Change ggml_backend_is_cpu logic to use GUID

* Remove redundant functions

Remove redundant functions `ggml_backend_i::get_name` and `ggml_backend_guid` which are not desired for future expansion

* Add spaces to match style

Co-authored-by: slaren <slarengh@gmail.com>

* Fix brace style to match

Co-authored-by: slaren <slarengh@gmail.com>

* Add void to () in function signature

Co-authored-by: slaren <slarengh@gmail.com>

* Add back ggml_backend_guid and make CPU_GUID a local static in ggml_backend_cpu_guid

* add guids to all backends

ggml-ci

---------

Co-authored-by: slaren <slarengh@gmail.com>
ggerganov pushed a commit to ggerganov/whisper.cpp that referenced this pull request Feb 25, 2024
* Introduce backend GUIDs

Initial proposed implementation of backend GUIDs
(Discussed in ggerganov/ggml#741)

Hardcoded CPU backend GUID (for now)
Change ggml_backend_is_cpu logic to use GUID

* Remove redundant functions

Remove redundant functions `ggml_backend_i::get_name` and `ggml_backend_guid` which are not desired for future expansion

* Add spaces to match style

Co-authored-by: slaren <slarengh@gmail.com>

* Fix brace style to match

Co-authored-by: slaren <slarengh@gmail.com>

* Add void to () in function signature

Co-authored-by: slaren <slarengh@gmail.com>

* Add back ggml_backend_guid and make CPU_GUID a local static in ggml_backend_cpu_guid

* add guids to all backends

ggml-ci

---------

Co-authored-by: slaren <slarengh@gmail.com>
ggerganov pushed a commit to ggerganov/llama.cpp that referenced this pull request Feb 28, 2024
* Introduce backend GUIDs

Initial proposed implementation of backend GUIDs
(Discussed in ggerganov/ggml#741)

Hardcoded CPU backend GUID (for now)
Change ggml_backend_is_cpu logic to use GUID

* Remove redundant functions

Remove redundant functions `ggml_backend_i::get_name` and `ggml_backend_guid` which are not desired for future expansion

* Add spaces to match style

Co-authored-by: slaren <slarengh@gmail.com>

* Fix brace style to match

Co-authored-by: slaren <slarengh@gmail.com>

* Add void to () in function signature

Co-authored-by: slaren <slarengh@gmail.com>

* Add back ggml_backend_guid and make CPU_GUID a local static in ggml_backend_cpu_guid

* add guids to all backends

ggml-ci

---------

Co-authored-by: slaren <slarengh@gmail.com>
github-actions bot pushed a commit to KerfuffleV2/ggml-sys-bleedingedge that referenced this pull request Feb 29, 2024
== Relevant log messages from source repo:

commit 317709b2a81dbaf87850202686ec5bb2602a504e
Author: Eve <139727413+netrunnereve@users.noreply.github.com>
Date:   Wed Feb 28 19:33:37 2024 +0000

    make portability_enumeration_ext apple only (#5757)

commit 08c5ee87e4cceb603ecceac90734fcdade57311b
Author: Georgi Gerganov <ggerganov@gmail.com>
Date:   Wed Feb 28 18:43:38 2024 +0200

    llama : remove deprecated API (#5770)

    ggml-ci

commit 2774b0c97427ee3ad3e2ee121354d078794e89d9
Author: slaren <slarengh@gmail.com>
Date:   Sun Feb 25 20:41:35 2024 +0100

    add google magika inference example (ggml/748)

    * add magika inference example

    * ggml : fix unaligned accesses in custom ops

    * ggml : fix FP32 GELU for values that exceed the FP16 range

    * use ggml_pool_1d

    * add README

    * Update README.md

    * pad inputs if the files are too small

    * cleanup

    ggml-ci

commit 5f706718566e3a5147916dc381f3b99de0ffad47
Author: UEXTM.com <84163508+uextm@users.noreply.github.com>
Date:   Sat Feb 24 11:27:36 2024 -0500

    Introduce backend GUIDs (ggml/743)

    * Introduce backend GUIDs

    Initial proposed implementation of backend GUIDs
    (Discussed in ggerganov/ggml#741)

    Hardcoded CPU backend GUID (for now)
    Change ggml_backend_is_cpu logic to use GUID

    * Remove redundant functions

    Remove redundant functions `ggml_backend_i::get_name` and `ggml_backend_guid` which are not desired for future expansion

    * Add spaces to match style

    Co-authored-by: slaren <slarengh@gmail.com>

    * Fix brace style to match

    Co-authored-by: slaren <slarengh@gmail.com>

    * Add void to () in function signature

    Co-authored-by: slaren <slarengh@gmail.com>

    * Add back ggml_backend_guid and make CPU_GUID a local static in ggml_backend_cpu_guid

    * add guids to all backends

    ggml-ci

    ---------

    Co-authored-by: slaren <slarengh@gmail.com>
jordankanter pushed a commit to jordankanter/llama.cpp that referenced this pull request Mar 13, 2024
* Introduce backend GUIDs

Initial proposed implementation of backend GUIDs
(Discussed in ggerganov/ggml#741)

Hardcoded CPU backend GUID (for now)
Change ggml_backend_is_cpu logic to use GUID

* Remove redundant functions

Remove redundant functions `ggml_backend_i::get_name` and `ggml_backend_guid` which are not desired for future expansion

* Add spaces to match style

Co-authored-by: slaren <slarengh@gmail.com>

* Fix brace style to match

Co-authored-by: slaren <slarengh@gmail.com>

* Add void to () in function signature

Co-authored-by: slaren <slarengh@gmail.com>

* Add back ggml_backend_guid and make CPU_GUID a local static in ggml_backend_cpu_guid

* add guids to all backends

ggml-ci

---------

Co-authored-by: slaren <slarengh@gmail.com>
hodlen pushed a commit to hodlen/llama.cpp that referenced this pull request Apr 1, 2024
* Introduce backend GUIDs

Initial proposed implementation of backend GUIDs
(Discussed in ggerganov/ggml#741)

Hardcoded CPU backend GUID (for now)
Change ggml_backend_is_cpu logic to use GUID

* Remove redundant functions

Remove redundant functions `ggml_backend_i::get_name` and `ggml_backend_guid` which are not desired for future expansion

* Add spaces to match style

Co-authored-by: slaren <slarengh@gmail.com>

* Fix brace style to match

Co-authored-by: slaren <slarengh@gmail.com>

* Add void to () in function signature

Co-authored-by: slaren <slarengh@gmail.com>

* Add back ggml_backend_guid and make CPU_GUID a local static in ggml_backend_cpu_guid

* add guids to all backends

ggml-ci

---------

Co-authored-by: slaren <slarengh@gmail.com>
jiahansu pushed a commit to WiseSync/whisper.cpp that referenced this pull request Apr 17, 2024
* Introduce backend GUIDs

Initial proposed implementation of backend GUIDs
(Discussed in ggerganov/ggml#741)

Hardcoded CPU backend GUID (for now)
Change ggml_backend_is_cpu logic to use GUID

* Remove redundant functions

Remove redundant functions `ggml_backend_i::get_name` and `ggml_backend_guid` which are not desired for future expansion

* Add spaces to match style

Co-authored-by: slaren <slarengh@gmail.com>

* Fix brace style to match

Co-authored-by: slaren <slarengh@gmail.com>

* Add void to () in function signature

Co-authored-by: slaren <slarengh@gmail.com>

* Add back ggml_backend_guid and make CPU_GUID a local static in ggml_backend_cpu_guid

* add guids to all backends

ggml-ci

---------

Co-authored-by: slaren <slarengh@gmail.com>
viktor-silakov pushed a commit to viktor-silakov/whisper_node_mic.cpp that referenced this pull request May 11, 2024
* Introduce backend GUIDs

Initial proposed implementation of backend GUIDs
(Discussed in ggerganov/ggml#741)

Hardcoded CPU backend GUID (for now)
Change ggml_backend_is_cpu logic to use GUID

* Remove redundant functions

Remove redundant functions `ggml_backend_i::get_name` and `ggml_backend_guid` which are not desired for future expansion

* Add spaces to match style

Co-authored-by: slaren <slarengh@gmail.com>

* Fix brace style to match

Co-authored-by: slaren <slarengh@gmail.com>

* Add void to () in function signature

Co-authored-by: slaren <slarengh@gmail.com>

* Add back ggml_backend_guid and make CPU_GUID a local static in ggml_backend_cpu_guid

* add guids to all backends

ggml-ci

---------

Co-authored-by: slaren <slarengh@gmail.com>
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.

None yet

2 participants