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

Python example in README doesn't work #248

Closed
ForceBru opened this issue Sep 19, 2021 · 7 comments · Fixed by #249
Closed

Python example in README doesn't work #248

ForceBru opened this issue Sep 19, 2021 · 7 comments · Fixed by #249

Comments

@ForceBru
Copy link

Your first Kompute (Python) says: AttributeError: module 'kp' has no attribute 'Shader'.

Code

The code is the same as in the README - I just imported kp and numpy as np on top. (BTW, it would be nice to be able to copy & paste this code and immediately run it, without adding the imports)

# test_kompute.py
import kp
import numpy as np

def kompute(shader):
    # 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
    mgr = kp.Manager()

    # 2. Create and initialise Kompute Tensors through manager

    # Default tensor constructor simplifies creation of float values
    tensor_in_a = mgr.tensor([2, 2, 2])
    tensor_in_b = mgr.tensor([1, 2, 3])
    # Explicit type constructor supports uint32, int32, double, float and bool
    tensor_out_a = mgr.tensor_t(np.array([0, 0, 0], dtype=np.uint32))
    tensor_out_b = mgr.tensor_t(np.array([0, 0, 0], dtype=np.uint32))

    params = [tensor_in_a, tensor_in_b, tensor_out_a, tensor_out_b]

    # 3. Create algorithm based on shader (supports buffers & push/spec constants)
    workgroup = (3, 1, 1)
    spec_consts = [2]
    push_consts_a = [2]
    push_consts_b = [3]

    # See documentation shader section for compile_source
    spirv = kp.Shader.compile_source(shader)

    algo = mgr.algorithm(params, spirv, workgroup, spec_consts, push_consts_a)

    # 4. Run operation synchronously using sequence
    (mgr.sequence()
        .record(kp.OpTensorSyncDevice(params))
        .record(kp.OpAlgoDispatch(algo)) # Binds default push consts provided
        .eval() # evaluates the two recorded ops
        .record(kp.OpAlgoDispatch(algo, push_consts_b)) # Overrides push consts
        .eval()) # evaluates only the last recorded op

    # 5. Sync results from the GPU asynchronously
    sq = mgr.sequence()
    sq.eval_async(kp.OpTensorSyncLocal(params))

    # ... Do other work asynchronously whilst GPU finishes

    sq.eval_await()

    # Prints the first output which is: { 4, 8, 12 }
    print(tensor_out_a)
    # Prints the first output which is: { 10, 10, 10 }
    print(tensor_out_b)

if __name__ == "__main__":

    # Define a raw string shader (or use the Kompute tools to compile to SPIRV / C++ header
    # files). This shader shows some of the main components including constants, buffers, etc
    shader = """
        #version 450

        layout (local_size_x = 1) in;

        // The input tensors bind index is relative to index in parameter passed
        layout(set = 0, binding = 0) buffer buf_in_a { float in_a[]; };
        layout(set = 0, binding = 1) buffer buf_in_b { float in_b[]; };
        layout(set = 0, binding = 2) buffer buf_out_a { uint out_a[]; };
        layout(set = 0, binding = 3) buffer buf_out_b { uint out_b[]; };

        // Kompute supports push constants updated on dispatch
        layout(push_constant) uniform PushConstants {
            float val;
        } push_const;

        // Kompute also supports spec constants on initalization
        layout(constant_id = 0) const float const_one = 0;

        void main() {
            uint index = gl_GlobalInvocationID.x;
            out_a[index] += uint( in_a[index] * in_b[index] );
            out_b[index] += uint( const_one * push_const.val );
        }
    """

    kompute(shader)

Running the code

~/test $ python3 test_kompute.py
Traceback (most recent call last):
  File "/Users/forcebru/test/test_kompute.py", line 81, in <module>
    kompute(shader)
  File "/Users/forcebru/test/test_kompute.py", line 26, in kompute
    spirv = kp.Shader.compile_source(shader)
AttributeError: module 'kp' has no attribute 'Shader'
libc++abi.dylib: terminating with uncaught exception of type pybind11::error_already_set: TypeError: 'NoneType' object is not callable
fish: Job 1, 'python3 test_kompute.py' terminated by signal SIGABRT (Abort)
~/test [SIGABRT] $

Side note: terminating with uncaught exception of type pybind11::error_already_set is probably a bug.

A comment in the code says See documentation shader section for compile_source, but I couldn't find this section. Furthermore, the documentation doesn't list Shader under Core Python components. The only documentation entry that mentions the compile_source function is this code, which just says spirv = compile_source(shader) and goes on assuming that the user knows what compile_source is.

I found a function called compile_source in the tests:

def compile_source(source):
open("tmp_kp_shader.comp", "w").write(source)
os.system("glslangValidator -V tmp_kp_shader.comp -o tmp_kp_shader.comp.spv")
return open("tmp_kp_shader.comp.spv", "rb").read()

Is this the function I should be using here?

Versions

  • macOS 10.15.7
  • NVIDIA GeForce GT 640M
  • Vulkan Instance Version: 1.2.189
  • Python 3.9.6
  • kp 0.8.0
@axsaucedo
Copy link
Member

Thank you very much for opening this issue @ForceBru ! This is indeed an error in the documentation, as the code has now been updated to use the util function instead of the internal dependency as per:

def compile_source(source):
open("tmp_kp_shader.comp", "w").write(source)
os.system("glslangValidator -V tmp_kp_shader.comp -o tmp_kp_shader.comp.spv")
return open("tmp_kp_shader.comp.spv", "rb").read()

@axsaucedo
Copy link
Member

I've merged now the change - would you be able to test with the updated script?

@ForceBru
Copy link
Author

ForceBru commented Sep 19, 2021

This says:

Traceback (most recent call last):
  File "/Users/forcebru/test/test_kompute.py", line 1, in <module>
    from .utils import compile_source
ImportError: attempted relative import with no known parent package

I just copied the code into /Users/forcebru/test/test_kompute.py, and the utils.py file isn't available there, of course. I manually added the code from python/test/utils.py:

import os

import kp
import numpy as np

def compile_source(source):
    open("tmp_kp_shader.comp", "w").write(source)
    os.system("glslangValidator -V tmp_kp_shader.comp -o tmp_kp_shader.comp.spv")
    return open("tmp_kp_shader.comp.spv", "rb").read()

def kompute(shader):
    # rest of the code

...and got this output:

~/test $ python3 test_kompute.py
tmp_kp_shader.comp
<kp.Tensor object at 0x1279145b0>
<kp.Tensor object at 0x10264f2b0>
~/test $

The comments, however, say:

# Prints the first output which is: { 4, 8, 12 }
print(tensor_out_a)
# Prints the first output which is: { 10, 10, 10 }
print(tensor_out_b)

So, the output is different.

Looks like the correct code should be calling .data, like this:

print(tensor_out_a.data())
print(tensor_out_b.data())

Then the output is:

tmp_kp_shader.comp
[ 4  8 12]
[10 10 10]

Why isn't the compile_source function part of the API, though? It seems to be really important, because I can't compile (and thus run) my shaders without it.

@axsaucedo
Copy link
Member

Yes that is correct, it's not part of the API, it's only used in the tests. This shouldn't be a blocker as if you do want to perform online compilation of shaders you can use https://github.com/realitix/pyshaderc.

For completeness, this was removed in v0.8.0 as the functionality was very much just for tests and was adding a lot of complexity via the glslang dependency #235

@ForceBru
Copy link
Author

Ah, so Kompute doesn't compile shaders, and one should be using either compile_source as a standalone function or the pyshaderc library. Got it, thanks!

@axsaucedo
Copy link
Member

That is correct - there's actually some documentation, but may be worth actually extending - I'll add this to have explicitly covered https://kompute.cc/overview/shaders-to-headers.html

@skuep2
Copy link

skuep2 commented Sep 27, 2023

By the way, this is still an issue with the Python Example here:
https://github.com/KomputeProject/kompute/tree/master/examples/python_naive_matmul

Traceback (most recent call last):
  File "/home/developer/Downloads/kompute/benchmark.py", line 56, in <module>
    main()
  File "/home/developer/Downloads/kompute/benchmark.py", line 35, in main
    matmul_op = MatMulOp(mgr)
  File "/home/developer/Downloads/kompute/imp1_naive.py", line 66, in __init__
    self.compiled_shader = kp.Shader.compile_source(self.shader.format(
AttributeError: module 'kp' has no attribute 'Shader'
terminate called after throwing an instance of 'pybind11::error_already_set'
  what():  TypeError: 'NoneType' object is not callable
Aborted (core dumped)

And still, the above problem with the wrong output is also present:

tmp_kp_shader.comp
<kp.Tensor object at 0x7fe60bec0030>
<kp.Tensor object at 0x7fe60bec00b0>

Changing it to print(tensor_out_a.data) outputs

tmp_kp_shader.comp
<bound method PyCapsule.data of <kp.Tensor object at 0x7f4b3612c7f0>>
<bound method PyCapsule.data of <kp.Tensor object at 0x7f4b3612c830>>

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 a pull request may close this issue.

3 participants