From afc8645ab81e7b9a958c2d64090ff4b24d8af698 Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Tue, 16 Apr 2024 00:10:34 -0400 Subject: [PATCH 1/6] add functions to choose GPU and get adapter info --- fastplotlib/__init__.py | 8 ++------ fastplotlib/utils/__init__.py | 1 + fastplotlib/utils/gpu.py | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 fastplotlib/utils/gpu.py diff --git a/fastplotlib/__init__.py b/fastplotlib/__init__.py index 8e6341156..f79de0c7c 100644 --- a/fastplotlib/__init__.py +++ b/fastplotlib/__init__.py @@ -7,17 +7,13 @@ from .layouts import Figure from .widgets import ImageWidget -from .utils import config - -import wgpu +from .utils import config, enumerate_adapters, select_adapter, print_wgpu_report with open(Path(__file__).parent.joinpath("VERSION"), "r") as f: __version__ = f.read().split("\n")[0] -adapters = [a.summary for a in wgpu.gpu.enumerate_adapters()] - -if len(adapters) < 1: +if len(enumerate_adapters()) < 1: raise IndexError("No WGPU adapters found, fastplotlib will not work.") diff --git a/fastplotlib/utils/__init__.py b/fastplotlib/utils/__init__.py index 6759b2497..e1eef6447 100644 --- a/fastplotlib/utils/__init__.py +++ b/fastplotlib/utils/__init__.py @@ -2,6 +2,7 @@ from .functions import * +from .gpu import enumerate_adapters, select_adapter, print_wgpu_report @dataclass diff --git a/fastplotlib/utils/gpu.py b/fastplotlib/utils/gpu.py new file mode 100644 index 000000000..72d303d23 --- /dev/null +++ b/fastplotlib/utils/gpu.py @@ -0,0 +1,24 @@ +import wgpu +from pygfx.renderers.wgpu import select_adapter as pygfx_select_adapter +from pygfx import print_wgpu_report as pygfx_print_wgpu_report + + +def enumerate_adapters() -> list[wgpu.GPUAdapter]: + return wgpu.gpu.enumerate_adapters() + + +enumerate_adapters.__doc__ = wgpu.gpu.enumerate_adapters.__doc__ + + +def select_adapter(adapter: wgpu.GPUAdapter): + return pygfx_select_adapter(adapter) + + +select_adapter.__doc__ = pygfx_select_adapter.__doc__ + + +def print_wgpu_report(): + return pygfx_print_wgpu_report() + + +print_wgpu_report.__doc__ = pygfx_print_wgpu_report.__doc__ From f1f47d8dc0ea70c4a5dcd47fec8f83f5323c4a03 Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Tue, 16 Apr 2024 00:10:53 -0400 Subject: [PATCH 2/6] add wgpu to intersphinx --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index a6a9fd1f6..f681a8101 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -53,6 +53,7 @@ "python": ("https://docs.python.org/3", None), "numpy": ("https://numpy.org/doc/stable/", None), "pygfx": ("https://pygfx.readthedocs.io/en/latest", None), + "wgpu": ("https://wgpu-py.readthedocs.io/en/latest", None), } html_theme_options = { From 636183af3575902cea7a3381180e46e54a348071 Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Tue, 16 Apr 2024 00:11:11 -0400 Subject: [PATCH 3/6] update gpu docs --- docs/source/api/gpu.rst | 5 + docs/source/index.rst | 9 +- docs/source/user_guide/gpu.rst | 279 ++++++++++++++++++++++++++++++--- 3 files changed, 268 insertions(+), 25 deletions(-) create mode 100644 docs/source/api/gpu.rst diff --git a/docs/source/api/gpu.rst b/docs/source/api/gpu.rst new file mode 100644 index 000000000..62ffd5797 --- /dev/null +++ b/docs/source/api/gpu.rst @@ -0,0 +1,5 @@ +fastplotlib.utils +***************** + +.. automodule:: fastplotlib.utils.gpu + :members: diff --git a/docs/source/index.rst b/docs/source/index.rst index 0ceb146e4..0bca839b9 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,8 +1,3 @@ -.. fastplotlib documentation master file, created by - sphinx-quickstart on Wed Dec 28 12:46:56 2022. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - Welcome to fastplotlib's documentation! ======================================= @@ -14,7 +9,7 @@ Welcome to fastplotlib's documentation! .. toctree:: :caption: User Guide - :maxdepth: 1 + :maxdepth: 2 GPU Info @@ -29,6 +24,7 @@ Welcome to fastplotlib's documentation! Selectors Widgets Utils + GPU Summary ======= @@ -36,7 +32,6 @@ Summary A fast plotting library built using the `pygfx `_ render engine utilizing `Vulkan `_, `DX12 `_, or `Metal `_ via `WGPU `_, so it is very fast! We also aim to be an expressive plotting library that enables rapid prototyping for large scale explorative scientific visualization. `fastplotlib` will run on any framework that ``pygfx`` runs on, this includes ``glfw``, ``Qt`` and ``jupyter lab`` - Installation ============ diff --git a/docs/source/user_guide/gpu.rst b/docs/source/user_guide/gpu.rst index 18fb81cdf..17f9a4a2d 100644 --- a/docs/source/user_guide/gpu.rst +++ b/docs/source/user_guide/gpu.rst @@ -1,8 +1,8 @@ -GPU Info -******** +GPU Info and selection +********************** FAQ ---- +=== 1. Do I need a GPU? @@ -10,7 +10,7 @@ Technically no, you can perform limited software rendering on linux using lavapi ``fastplotlib`` is intentionally built for realtime rendering using the latest GPU technologies, so we strongly recommend that you use a GPU. -2. My kernel keeps crashing when I create visualizations. +2. My kernel keeps crashing. This can happen under the following circumstances: @@ -19,24 +19,29 @@ This can happen under the following circumstances: If you aren't able to solve it please post an issue on GitHub. :) +3. Nothing renders or rendering is weird, or I see graphical artifacts. + +- Probably driver issues (see next section). + Drivers -------- +======= See the README: https://github.com/fastplotlib/fastplotlib?tab=readme-ov-file#graphics-drivers If you notice weird graphic artifacts, things not rendering, or other glitches try updating to the latest stable drivers. +GPU Info +======== -View available GPU ------------------- +View available adapters +----------------------- -You can view all GPUs that are available to ``WGPU`` like this:: +You can get a summary of all adapters that are available to ``WGPU`` like this:: - import wgpu + import fastplotlib as fpl - for adapter in wgpu.gpu.enumerate_adapters(): - print(adapter.summary) + print([a.summary for a in fpl.enumerate_adapters()]) For example, on a Thinkpad AMD laptop with a dedicated nvidia GPU this returns:: @@ -45,17 +50,255 @@ For example, on a Thinkpad AMD laptop with a dedicated nvidia GPU this returns:: llvmpipe (LLVM 15.0.6, 256 bits) (CPU) on Vulkan AMD Radeon Graphics (rembrandt, LLVM 15.0.6, DRM 3.52, 6.4.0-0.deb12.2-amd64) (Unknown) on OpenGL +In jupyter all the available adapters are also listed when ``fastplotlib`` is imported. + +You can get more detailed info on each adapter like this:: + + print([a.request_adapter_info() for a in fpl.enumerate_adapters()]) + +General description of the fields: + * vendor: GPU manufacturer + * device: specific GPU model + * description: GPU driver version + * adapter_type: indicates whether this is a discrete GPU, integrated GPU, or software rendering adapter (CPU) + * backend_type: one of "Vulkan", "Metal", or "D3D12" -GPU currently in use --------------------- +For more information on the fields see: https://gpuweb.github.io/gpuweb/#gpuadapterinfo -If you want to know the GPU that a current plot is using you can check the adapter that the renderer is using:: +Adapter currently in use +------------------------ + +If you want to know the adapter that a figure is using you can check the adapter on the renderer:: # for example if we make a plot - plot = fpl.Plot() - plot.add_image(np.random.rand(100, 100)) - plot.show() + fig = fpl.Figure() + fig[0, 0].add_image(np.random.rand(100, 100)) + fig.show() # GPU that is currently in use by the renderer - print(plot.renderer.device.adapter.summary) + print(fig.renderer.device.adapter.summary) + + +Diagnostic info +--------------- + +After creating a figure you can view WGPU diagnostic info like this:: + + fpl.print_wgpu_report() + + +Example output:: + + ██ system: + + platform: Linux-5.10.0-21-amd64-x86_64-with-glibc2.31 + python_implementation: CPython + python: 3.11.3 + + ██ versions: + + wgpu: 0.15.1 + cffi: 1.15.1 + jupyter_rfb: 0.4.2 + numpy: 1.26.4 + pygfx: 0.2.0 + pylinalg: 0.4.1 + fastplotlib: 0.1.0.a16 + + ██ wgpu_native_info: + + expected_version: 0.19.3.1 + lib_version: 0.19.3.1 + lib_path: ./resources/libwgpu_native-release.so + + ██ object_counts: + + count resource_mem + + Adapter: 1 + BindGroup: 3 + BindGroupLayout: 3 + Buffer: 6 696 + CanvasContext: 1 + CommandBuffer: 0 + CommandEncoder: 0 + ComputePassEncoder: 0 + ComputePipeline: 0 + Device: 1 + PipelineLayout: 0 + QuerySet: 0 + Queue: 1 + RenderBundle: 0 + RenderBundleEncoder: 0 + RenderPassEncoder: 0 + RenderPipeline: 3 + Sampler: 2 + ShaderModule: 3 + Texture: 6 9.60M + TextureView: 6 + + total: 36 9.60M + + ██ wgpu_native_counts: + + count mem backend a k r e el_size + + Adapter: 1 1.98K vulkan: 1 1 3 0 1.98K + BindGroup: 3 1.10K vulkan: 3 3 0 0 368 + BindGroupLayout: 3 960 vulkan: 5 3 2 0 320 + Buffer: 6 1.77K vulkan: 7 6 1 0 296 + CanvasContext: 0 0 0 0 0 0 160 + CommandBuffer: 1 1.25K vulkan: 0 0 0 1 1.25K + ComputePipeline: 0 0 vulkan: 0 0 0 0 288 + Device: 1 11.8K vulkan: 1 1 0 0 11.8K + PipelineLayout: 0 0 vulkan: 3 0 3 0 200 + QuerySet: 0 0 vulkan: 0 0 0 0 80 + Queue: 1 184 vulkan: 1 1 0 0 184 + RenderBundle: 0 0 vulkan: 0 0 0 0 848 + RenderPipeline: 3 1.68K vulkan: 3 3 0 0 560 + Sampler: 2 160 vulkan: 2 2 0 0 80 + ShaderModule: 3 2.40K vulkan: 3 3 0 0 800 + Texture: 6 4.94K vulkan: 7 6 1 0 824 + TextureView: 6 1.48K vulkan: 6 6 1 0 248 + + total: 36 29.7K + + * The a, k, r, e are allocated, kept, released, and error, respectively. + * Reported memory does not include buffer/texture data. + + ██ pygfx_adapter_info: + + vendor: radv + architecture: + device: AMD RADV POLARIS10 (ACO) + description: Mesa 20.3.5 (ACO) + vendor_id: 4.09K + device_id: 26.5K + adapter_type: DiscreteGPU + backend_type: Vulkan + + ██ pygfx_features: + + adapter device + + bgra8unorm-storage: - - + depth32float-stencil8: ✓ - + depth-clip-control: ✓ - + float32-filterable: ✓ ✓ + indirect-first-instance: ✓ - + rg11b10ufloat-renderable: ✓ - + shader-f16: - - + texture-compression-astc: - - + texture-compression-bc: ✓ - + texture-compression-etc2: - - + timestamp-query: ✓ - + MultiDrawIndirect: ✓ - + MultiDrawIndirectCount: ✓ - + PushConstants: ✓ - + TextureAdapterSpecificFormatFeatures: ✓ - + VertexWritableStorage: ✓ - + + ██ pygfx_limits: + + adapter device + + max_bind_groups: 8 8 + max_bind_groups_plus_vertex_buffers: 0 0 + max_bindings_per_bind_group: 1.00K 1.00K + max_buffer_size: 2.14G 2.14G + max_color_attachment_bytes_per_sample: 0 0 + max_color_attachments: 0 0 + max_compute_invocations_per_workgroup: 1.02K 1.02K + max_compute_workgroup_size_x: 1.02K 1.02K + max_compute_workgroup_size_y: 1.02K 1.02K + max_compute_workgroup_size_z: 1.02K 1.02K + max_compute_workgroup_storage_size: 32.7K 32.7K + max_compute_workgroups_per_dimension: 65.5K 65.5K + max_dynamic_storage_buffers_per_pipeline_layout: 8 8 + max_dynamic_uniform_buffers_per_pipeline_layout: 16 16 + max_inter_stage_shader_components: 128 128 + max_inter_stage_shader_variables: 0 0 + max_sampled_textures_per_shader_stage: 8.38M 8.38M + max_samplers_per_shader_stage: 8.38M 8.38M + max_storage_buffer_binding_size: 2.14G 2.14G + max_storage_buffers_per_shader_stage: 8.38M 8.38M + max_storage_textures_per_shader_stage: 8.38M 8.38M + max_texture_array_layers: 2.04K 2.04K + max_texture_dimension1d: 16.3K 16.3K + max_texture_dimension2d: 16.3K 16.3K + max_texture_dimension3d: 2.04K 2.04K + max_uniform_buffer_binding_size: 2.14G 2.14G + max_uniform_buffers_per_shader_stage: 8.38M 8.38M + max_vertex_attributes: 32 32 + max_vertex_buffer_array_stride: 2.04K 2.04K + max_vertex_buffers: 16 16 + min_storage_buffer_offset_alignment: 32 32 + min_uniform_buffer_offset_alignment: 32 32 + + ██ pygfx_caches: + + count hits misses + + full_quad_objects: 1 0 2 + mipmap_pipelines: 0 0 0 + layouts: 1 0 3 + bindings: 1 0 1 + shader_modules: 2 0 2 + pipelines: 2 0 2 + shadow_pipelines: 0 0 0 + + ██ pygfx_resources: + + Texture: 8 + Buffer: 23 + + +Select GPU (adapter) +==================== + +You can select an adapter by passing one of the ``wgpu.GPUAdapter`` instances returned by ``fpl.enumerate_adapters()`` +to ``fpl.select_adapter()``:: + + # get info or summary of all adapters to pick an adapter + print([a.request_adapter_info() for a in fpl.enumerate_adapters()]) + + # example, pick adapter at index 2 + chosen_gpu = fpl.enumerate_adapters()[2] + fpl.select_adapter(chosen_gpu) + +Note that using this function reduces the portability of your code, because +it's highly specific for your current machine/environment. + +The order of the adapters returned by ``wgpu.gpu.enumerate_adapters()`` is +such that Vulkan adapters go first, then Metal, then D3D12, then OpenGL. +Within each category, the order as provided by the particular backend is +maintained. Note that the same device may be present via multiple backends +(e.g. vulkan/opengl). + +We cannot make guarantees about whether the order of the adapters matches +the order as reported by e.g. ``nvidia-smi``. We have found that on a Linux +multi-gpu cluster, the order does match, but we cannot promise that this is +always the case. If you want to make sure, do some testing by allocating big +buffers and checking memory usage using ``nvidia-smi`` + +Example to allocate and check GPU mem usage:: + + import subprocess + + import wgpu + import torch + + def allocate_gpu_mem_with_wgpu(idx): + a = wgpu.gpu.enumerate_adapters()[idx] + d = a.request_device() + b = d.create_buffer(size=10*2**20, usage=wgpu.BufferUsage.COPY_DST) + return b + + def allocate_gpu_mem_with_torch(idx): + d = torch.device(f"cuda:{idx}") + return torch.ones([2000, 10], dtype=torch.float32, device=d) + + def show_mem_usage(): + print(subprocess.run(["nvidia-smi"])) +See https://github.com/pygfx/wgpu-py/issues/482 for more details. From f56b244cfd624c33070b9bd5544d2167fdcbba89 Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Tue, 16 Apr 2024 11:04:20 -0400 Subject: [PATCH 4/6] update docs --- docs/source/user_guide/gpu.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/source/user_guide/gpu.rst b/docs/source/user_guide/gpu.rst index 17f9a4a2d..0cf6c147c 100644 --- a/docs/source/user_guide/gpu.rst +++ b/docs/source/user_guide/gpu.rst @@ -41,7 +41,10 @@ You can get a summary of all adapters that are available to ``WGPU`` like this:: import fastplotlib as fpl - print([a.summary for a in fpl.enumerate_adapters()]) + adapters = fpl.enumerate_adapters() + + for a in adapters: + print(a.summary) For example, on a Thinkpad AMD laptop with a dedicated nvidia GPU this returns:: @@ -54,7 +57,9 @@ In jupyter all the available adapters are also listed when ``fastplotlib`` is im You can get more detailed info on each adapter like this:: - print([a.request_adapter_info() for a in fpl.enumerate_adapters()]) + import pprint + for a in fpl.enumerate_adapters(): + pprint.pprint(a.request_adapter_info()) General description of the fields: * vendor: GPU manufacturer From cc3ca2939f24978f8c254983beec8bf3f5773aa8 Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Tue, 16 Apr 2024 11:06:46 -0400 Subject: [PATCH 5/6] update docsg --- docs/source/user_guide/gpu.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/user_guide/gpu.rst b/docs/source/user_guide/gpu.rst index 0cf6c147c..92151922b 100644 --- a/docs/source/user_guide/gpu.rst +++ b/docs/source/user_guide/gpu.rst @@ -271,6 +271,9 @@ to ``fpl.select_adapter()``:: chosen_gpu = fpl.enumerate_adapters()[2] fpl.select_adapter(chosen_gpu) +**You must select an adapter before creating a ``Figure``, otherwise the default adapter will be selected. Once a +``Figure`` is created the adapter cannot be changed.** + Note that using this function reduces the portability of your code, because it's highly specific for your current machine/environment. From 532924de6ad18d095b4c2f954a8eccc6aeeb2960 Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Tue, 16 Apr 2024 11:14:28 -0400 Subject: [PATCH 6/6] why is rst so weird --- docs/source/user_guide/gpu.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/user_guide/gpu.rst b/docs/source/user_guide/gpu.rst index 92151922b..3f4ff4bb4 100644 --- a/docs/source/user_guide/gpu.rst +++ b/docs/source/user_guide/gpu.rst @@ -271,8 +271,8 @@ to ``fpl.select_adapter()``:: chosen_gpu = fpl.enumerate_adapters()[2] fpl.select_adapter(chosen_gpu) -**You must select an adapter before creating a ``Figure``, otherwise the default adapter will be selected. Once a -``Figure`` is created the adapter cannot be changed.** +**You must select an adapter before creating a** ``Figure`` **, otherwise the default adapter will be selected. Once a** +``Figure`` **is created the adapter cannot be changed.** Note that using this function reduces the portability of your code, because it's highly specific for your current machine/environment. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy