<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Production ML, responsible AI and alignment blog</title><description>Writing from The Institute for Ethical AI Alignment &amp; Safety on production machine learning, responsible AI and AI safety.</description><link>https://ethical.institute/</link><language>en</language><item><title>Whose Memory Is It? Building Multi-Tenant, Multi-Tier Memory for AI Agents (Part 2)</title><link>https://ethical.institute/blog/whose-memory-is-it-part-2/</link><guid isPermaLink="true">https://ethical.institute/blog/whose-memory-is-it-part-2/</guid><description>This is a 4-part series on how agents remember: building short-, medium- and long-term memory that scales across users, agents, and kubernetes clusters.</description><pubDate>Mon, 10 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;Alice and bob are talking to the same agents. Alice interacts with various agents for infra management. Bob interacts with various agents for app development. Both are able to build on learnings from the last month. But how far should this go? Should Alice be able to recall memories from Bob’s interactions? Should a user allow a single agent to recall memories from across their agents?&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;This captures the design choices required in multi-tenancy for agentic memory management&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;Recently I spent some time extending the &lt;a href=&quot;https://github.com/axsaucedo/agentic-kubernetes-operator&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kubernetes Agent Orchestration System (KAOS)&lt;/a&gt; to support multi-tiered memory persistence (aka short-, medium- and long-term memory). Along the way I hit most of the same issues that anyone would whilst building or integrating multi-tiered memory into a multi-tenant system, so I thought it would be useful to compile the learnings, design choices and examples into this series.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is Part 2 of the series, and here I go through some of the design choices made for 3-tier multi-tenant memory. This follows &lt;a href=&quot;https://www.linkedin.com/pulse/whose-memory-building-multi-tenant-multi-tier-ai-agents-saucedo-kvcsf/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Part 1&lt;/a&gt;, where we surveyed ~30 memory engines, built a working taxonomy, and landed on adopting &lt;a href=&quot;https://github.com/mem0ai/mem0&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mem0&lt;/a&gt; as a library behind our own interface, together with the list of gaps (observability, tenant isolation, kubernetes packaging, framework bridging) that become our integration work.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The objective throughout the series is:&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;Let’s make the memory layer BORING, so that the agents can continue to be the fun part.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;This part consists of two sections:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Three memory tiers&lt;/strong&gt;: Defining the memory adopted, which includes a short-term window memory, a medium-term rolling summary, and long-term semantic “facts”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scope model&lt;/strong&gt;: A hierarchical multi-tenant read model scope, that spans across &lt;code&gt;session &gt; agent &gt; user&lt;/code&gt;, defined by a verified identity and a &lt;code&gt;maxReadScope&lt;/code&gt; ceiling&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally we wrap up with five hard lessons we learned about tier and scope design that carry beyond KAOS.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As with my previous posts on &lt;a href=&quot;https://hackernoon.com/production-observability-for-multi-agent-ai-with-kaos-otel-signoz&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;observability for agentic systems&lt;/a&gt; and &lt;a href=&quot;https://hackernoon.com/autonomous-agentic-systems-a-practical-guide-to-always-on-agents&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;autonomous always-on agentic patterns&lt;/a&gt;, I use KAOS as the concrete implementation example, but the goal is to provide practical intuition for the primitives (tiers, scopes, folding, degradation), so that it applies whether you use KAOS, Mem0 directly, LangGraph, CrewAI, or a memory layer you wrote yourself.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Here’s a refresher on this 4-part series on Multi-Tiered / Multi-Tenant Agent Memory:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.linkedin.com/pulse/whose-memory-building-multi-tenant-multi-tier-ai-agents-saucedo-kvcsf/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Part 1: What agent memory is and what to build on.&lt;/a&gt;&lt;/strong&gt; The taxonomy, the baseline implementations everyone starts with, and the engine landscape from surveying ~30 tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 2 (this post): Tiers and scopes for multi-tenant agents.&lt;/strong&gt; The three-tier design and the answer to whose memory it is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 3: Memory as infrastructure.&lt;/strong&gt; The Kubernetes &lt;code&gt;MemoryStore&lt;/code&gt; resource, its deployment topology, and how to integrate it in your own agent (coming soon…).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 4: Agent memory in action.&lt;/strong&gt; A worked example that runs end to end on a secured cluster, with real outputs (coming soon…).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s get started.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;designing-our-memory-architecture-the-three-tiers&quot;&gt;Designing our Memory Architecture: The Three Tiers&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;As a reminder, the taxonomy defined in &lt;a href=&quot;https://www.linkedin.com/pulse/whose-memory-building-multi-tenant-multi-tier-ai-agents-saucedo-kvcsf/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Part 1&lt;/a&gt; consisted of five memory types: short-term (working), episodic, semantic, procedural and temporal.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;However when aligning with our requirements, I settled with a simplified &lt;strong&gt;three tier model&lt;/strong&gt;: a short-term &lt;strong&gt;window&lt;/strong&gt;, a medium-term &lt;strong&gt;summary&lt;/strong&gt;, and long-term &lt;strong&gt;“facts”&lt;/strong&gt;. These are intuitively defined as follows:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;




























&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tier&lt;/th&gt;&lt;th&gt;What it holds&lt;/th&gt;&lt;th&gt;When it updates&lt;/th&gt;&lt;th&gt;Backing&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Short-term&lt;/td&gt;&lt;td&gt;The context window of the live session, bounded by a token budget&lt;/td&gt;&lt;td&gt;Every turn (cheap append)&lt;/td&gt;&lt;td&gt;Relational rows&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Medium-term&lt;/td&gt;&lt;td&gt;Rolling summary per session, versioned so past summaries stay accessible&lt;/td&gt;&lt;td&gt;On compaction, when the window hits its token budget&lt;/td&gt;&lt;td&gt;Relational rows, append-only&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Long-term&lt;/td&gt;&lt;td&gt;Atomic facts extracted from context window, keyed by scope, recalled semantically&lt;/td&gt;&lt;td&gt;In the background, after compaction&lt;/td&gt;&lt;td&gt;Mem0 into the vector store&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that these tiers are defined, it was possible to also formalise the following design decisions:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Long-term memory functionality is enabled via Mem0; short- and medium-term memory are built custom.&lt;/li&gt;
&lt;li&gt;These three tiers should cohesively integrate as a single interoperable unit.&lt;/li&gt;
&lt;li&gt;Medium- and long-term extraction &lt;strong&gt;is lossy&lt;/strong&gt;; &lt;a href=&quot;https://arxiv.org/abs/2605.04897&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;we could enable provenance&lt;/a&gt;, however this adds significant complexity so I decided to keep this out of scope for now.&lt;/li&gt;
&lt;li&gt;Medium- and long-term extraction are always &lt;strong&gt;off the write path&lt;/strong&gt;; it triggers when compaction threshold is crossed as opposed to in every insert, which is also how &lt;a href=&quot;https://docs.mem0.ai/core-concepts/memory-operations&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mem0’s own platform behaves&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The medium-term summary stays &lt;strong&gt;out of the vector store&lt;/strong&gt;: Mem0 wants atomic, individually revisable facts, whereas a summary is a narrative whose whole value is its continuity.&lt;/li&gt;
&lt;li&gt;Underneath all three tiers, the &lt;strong&gt;raw turns are the source of truth&lt;/strong&gt; and everything else (summaries, facts, embeddings) is a recomputable projection, which is also what makes lossy extraction and fire-and-forget background processing acceptable.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/2501.13956&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Temporal&lt;/a&gt; (bi-temporal validity) and &lt;a href=&quot;https://arxiv.org/abs/2309.02427&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;procedural&lt;/a&gt; (aka skill persistence) memory are deliberately &lt;strong&gt;deferred&lt;/strong&gt; in their explicit form, but achievable through the long-term memory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;These definitions also allow us to design the single coherent service that offers the short-, medium- and long-term memory tiers; the &lt;strong&gt;“MemoryStore Service”&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./memory-store-tiers.svg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;MemoryStore service connecting an agent runtime to short-, medium-, and long-term memory&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;I will cover more on the &lt;code&gt;MemoryStore&lt;/code&gt; service in Part 3 where we actually design the infrastructure components for Kubernetes. Before we get there however, we need to talk about another important (+ tricky) topic:&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Access Scopes&lt;/strong&gt;: or &lt;strong&gt;who&lt;/strong&gt; should be able to remember &lt;strong&gt;what&lt;/strong&gt;?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;access-scopes-whose-memory-is-it-anyway&quot;&gt;Access Scopes: Whose Memory Is It Anyway?&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Every memory operation in a multi-tenant system needs an answer to “whose memory is it?”. And the answer has to come from the design of the system components.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We first have to start on the &lt;strong&gt;write path&lt;/strong&gt; before we can define a solution for the &lt;strong&gt;read path access&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For the write, the constraint introduced was the following:&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;A single conversation is authored through an agent, on behalf of a user (or autonomous agent), inside of a session, on one memory store.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;This means the service records all of these as metadata provenance for every memory input stored. Writes are therefore compound and invariant, while a read resolves to a single scope level and is a matter of policy.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;That separation is what lets a write be recalled at several levels later without being duplicated. This is possible because the same memory data that an agent stored for “Alice” carries: 1) her &lt;code&gt;user_id&lt;/code&gt;, 2) the agent identity, and 3) the session identifier.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This allows recalls at different levels to each find it through a different owner key.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./stored-fact-scopes.svg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;One stored fact recalled at session, agent, and user scopes&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For reads, we decided to use a hierarchical relationship across these three levels, where each wider level contains the previous one:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./scope-hierarchy.svg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Nested memory scopes from session through agent, user, and store&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The access scope is what restricts read-level access, as it can be understood intuitively in the graph above.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This gives each level one documented meaning under each security posture:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;


































&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Level&lt;/th&gt;&lt;th&gt;Meaning&lt;/th&gt;&lt;th&gt;With user auth on&lt;/th&gt;&lt;th&gt;With user auth off&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;session&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the current conversation&lt;/td&gt;&lt;td&gt;current agent x user x session&lt;/td&gt;&lt;td&gt;current agent x session&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;agent&lt;/code&gt;&lt;/td&gt;&lt;td&gt;this agent’s memory of the verified context&lt;/td&gt;&lt;td&gt;current agent x user&lt;/td&gt;&lt;td&gt;this agent’s whole pool&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;user&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the verified user across all agents on the store&lt;/td&gt;&lt;td&gt;current user, across agents&lt;/td&gt;&lt;td&gt;rejected at deploy time&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;store&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the entire memory store for the agents using it&lt;/td&gt;&lt;td&gt;all users x agents x sessions in that store&lt;/td&gt;&lt;td&gt;all agents x sessions&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;The identity always comes from the gateway-verified request headers, never from the request body or the model, which means that when auth is enabled, memory access is enforced by design at the control and data plane level.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The only way to access the &lt;code&gt;store&lt;/code&gt; level (or the agent-wide pool across users) is through cluster-admin permissions: the memory service refuses these levels on any request arriving through an agent, so no grant, tool, or prompt can reach them, and the only remaining path is &lt;code&gt;kubectl port-forward&lt;/code&gt;, which Kubernetes RBAC gates. If auth is disabled, the level meanings still hold logically, however there is no verified identity to enforce them against.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./store-access-boundary.svg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Store-level memory access refused for models and allowed through RBAC-gated operator access&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Because the read levels are totally ordered as a hierarchy, we are also able to define them with a &lt;code&gt;maxReadScope&lt;/code&gt; that allows for a threshold definition (for example “max agent level and below”).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This also allows the &lt;code&gt;MemoryStore&lt;/code&gt; to carry its own &lt;code&gt;maxReadScope&lt;/code&gt; ceiling (default is &lt;code&gt;agent&lt;/code&gt;), and an agent may not claim above its store’s, so cross-agent &lt;code&gt;user&lt;/code&gt; reads exist only where the store owner deliberately raised the ceiling.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./max-read-scope.svg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;MemoryStore and agent maximum read-scope ceilings&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As covered in my previous post on &lt;a href=&quot;https://hackernoon.com/autonomous-agentic-systems-a-practical-guide-to-always-on-agents&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;autonomous always-on agents&lt;/a&gt;, KAOS supports agents that run without user input. I was able to also cover these instances by ensuring that a self-initiated iteration runs with the agent’s own identity as its user identifier. This means that all requirements for memory scopes are still satisfied, and an autonomous loop’s memory stays private to the loop, even if a user also queries that same autonomous agent.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This scope model is probably the obvious choice; the trickier question is how do we enforce the &lt;strong&gt;sharing restrictions&lt;/strong&gt; at a project-like scope.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;There were a few design options for this:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Many groups inside one MemoryStore.&lt;/strong&gt; One store holds the memories of several groups at once. This sounds efficient, however it means building and operating a whole group-management layer. This would involve an API to create and delete groups and to add and remove members, per-group quotas, and a single store whose failure affects every group in it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One group per MemoryStore.&lt;/strong&gt; The store itself is the group: whichever agents are bound to the same store share it, so membership is just the existing binding and no new API is needed. The cost is that every group needs its own store deployment, and sharing across two groups means binding to a second store.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hierarchical scope paths.&lt;/strong&gt; A richer model where scopes are nested paths (for example &lt;code&gt;org:team:agent&lt;/code&gt;) and agents share memory up to the point where their paths diverge. Every version of this I drafted ended up re-creating an authorization system that the two simpler options already covered.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;Interestingly enough, when looking at how the managed platforms handle this, they expose a two-level version of the same tradeoff. Each one has a hard container that their control plane creates and manages, and lighter logical partitions inside it. A few examples:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.mem0.ai/platform/platform-vs-oss&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mem0 platform&lt;/a&gt;: A project is the container that memories cannot cross, and the user and agent partitions live within it, with API keys scoped to the project.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.cloud.google.com/agent-builder/agent-engine/memory-bank/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Vertex Memory Bank&lt;/a&gt;: Provisions one Memory Bank per Agent Engine instance, and within it memories are partitioned by scope, with retrieval only returning memories whose scope exactly matches the request.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.getzep.com/platform/graphiti/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Zep Cloud&lt;/a&gt;: Each subject (a user, or a group via their group-graph API) gets its own isolated context graph, and the cloud platform is the control plane that manages millions of them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Based on these tradeoffs, I went for option (2), one group per MemoryStore as it enforces this at the control plane. The store itself is the sharing boundary, which is exactly why the whole-store read scope is named &lt;code&gt;store&lt;/code&gt;. This meant that I don’t have to build a full intra-store group management layer, and the data layer simply records the store’s group key as internal metadata on each record.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The way it’s designed to is set up to support finer grouping at the &lt;code&gt;MemoryStore&lt;/code&gt; level by design, as we basically are storing everything under one global group per store.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now finally once I adopted these design choices, I realised that there were a few caveats that came up, which I had to accept / address:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Security Attack Surfaces&lt;/strong&gt;: Interesting research such as &lt;a href=&quot;https://arxiv.org/abs/2407.12784&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AgentPoison&lt;/a&gt; show the impact of poisoning memory (ie 0.1% poisoned memory yields over 80% attack success), as well as &lt;a href=&quot;https://arxiv.org/abs/2503.03704&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MINJA&lt;/a&gt; which shows that an attacker needs no write access at all, because if the agent writes its own memory from conversations then every user is a write path. &lt;strong&gt;To mitigate this&lt;/strong&gt;, it was decided for KAOS to derive the scope server-side from the authenticated agent identity, fail-closed, and never from model- or tool-supplied arguments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Depth of intra-store isolation&lt;/strong&gt;: Within one store, the boundaries between agents, users and sessions are enforced by application-level filtering. Application-level predicates carry a classic risk, where one forgotten &lt;code&gt;WHERE&lt;/code&gt; clause silently returns another tenant’s rows. &lt;strong&gt;To mitigate this&lt;/strong&gt;, the filtering is centralised in a single storage module so there is one place to audit, and on Postgres the relational tiers can be hardened further with &lt;a href=&quot;https://www.postgresql.org/docs/current/ddl-rowsecurity.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;row-level security&lt;/a&gt;, where a &lt;code&gt;FORCE ROW LEVEL SECURITY&lt;/code&gt; policy pins every query to the scope set on the transaction, so a missing predicate returns nothing instead of everything. Worth noting this RLS cannot be enforced at the vector level - however isolation &lt;em&gt;between&lt;/em&gt; stores relies on none of this, since each store is its own deployment with its own database connection, which we cover in Part 3.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Right to Erasure&lt;/strong&gt;: Compliance requirements such as GDPR mean you must be able to answer “delete everything you know about this user” reliably, and in a multi-tier design the same information lives in several derived forms at once (raw turns, summaries, extracted facts, and their embeddings), so deleting from one tier is not enough. &lt;strong&gt;To mitigate this&lt;/strong&gt;, KAOS implements &lt;code&gt;forget&lt;/code&gt; as a single operation that fans out across all three tiers in one pass, deleting the short-term rows, the summaries, and the scope-filtered long-term facts. Note this is destruction, which is different from supersession, where facts are merely marked invalid but kept for history.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have sorted the tiers and the access scopes, let’s distil the lessons from this part before we make it all run as infrastructure in part 3.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;lessons-for-production-agentic-memory&quot;&gt;Lessons for Production Agentic Memory&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Here are the patterns from this part that I would carry into any agentic memory system.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-separate-conversational-continuity-from-learned-knowledge&quot;&gt;1. Separate conversational continuity from learned knowledge&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Same-session verbatim windows and cross-session distilled facts are different memory tiers with different stores, lifecycles, and failure modes. Conflating them for any reason would add more complexity than simplification.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-raw-conversations-are-the-source-of-truth&quot;&gt;2. Raw conversations are the source of truth&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Summaries, facts, and embeddings are lossy, but recomputable. Keep the verbatim record durable and you can survive both a lost extraction and a change of mind about your extraction strategy.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-keep-rolling-summaries-out-of-the-vector-store&quot;&gt;3. Keep rolling summaries out of the vector store&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We use long-term memory stores for atomic facts, whereas the medium-term memory is built with a rolling summary that provides continuity. Summaries and windows can be stored relationally and deterministically.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;4-the-control-plane-should-enforce-the-memory-scope&quot;&gt;4. The control plane should enforce the memory scope&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Derive scope server-side from authenticated identity. When the model is allowed to search, bound the levels it can reach with a &lt;code&gt;maxReadScope&lt;/code&gt; ceiling. Treat what comes back as untrusted data with provenance, since memory poisoning and cross-session injection are demonstrated attacks with published success rates.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;5-the-store-is-the-group-and-vice-versa&quot;&gt;5. The store is the group (and vice-versa)&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Sharing topology can be a deployment choice instead of an authorization system, with scope filtering within a store and physical isolation by deploying a store per tenant. This may seem restrictive, but it’s the model that most production platforms (+ cloud providers) follow.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;closing-thoughts-for-part-2&quot;&gt;Closing Thoughts for Part 2&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;We opened Part 2 with Alice and Bob talking to the same agents, and with the question of how should their memories be available and accessable. After this initial design, we can now answer it precisely.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Should Alice recall memories from Bob’s interactions? Never through an agent, because every recall is bound to the verified identity on the request.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Should a single agent reach across a user’s other agents? Only when the user level sits within its &lt;code&gt;maxReadScope&lt;/code&gt; ceiling, which both the agent and the store owner have to allow.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Everything wider than that belongs to the cluster admin, behind Kubernetes RBAC.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;That is the conceptual core of the series: three tiers that decide what an agent remembers, and a scope model that decides who it remembers it for.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In Part 3 we turn this design into running infrastructure with the &lt;code&gt;MemoryStore&lt;/code&gt; Kubernetes resource, the topology decision behind it, and the degradation contract that keeps a memory outage from taking an agent down, together with how you can integrate the same pattern in your own agent from scratch.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Stay tuned for next week!&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;The series:&lt;/strong&gt;&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.linkedin.com/pulse/whose-memory-building-multi-tenant-multi-tier-ai-agents-saucedo-kvcsf/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Part 1: What agent memory is and what to build on.&lt;/a&gt;&lt;/strong&gt; The taxonomy, the baseline implementations everyone starts with, and the engine landscape from surveying ~30 tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 2 (this post): Tiers and scopes for multi-tenant agents.&lt;/strong&gt; The three-tier design and the answer to whose memory it is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 3: Memory as infrastructure.&lt;/strong&gt; The Kubernetes &lt;code&gt;MemoryStore&lt;/code&gt; resource, its deployment topology, and how to integrate it in your own agent (coming soon…).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 4: Agent memory in action.&lt;/strong&gt; A worked example that runs end to end on a secured cluster, with real outputs (coming soon…).&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded><category>agents</category><category>memory</category><category>kubernetes</category></item><item><title>Whose Memory Is It? Building Multi-Tenant, Multi-Tier Memory for AI Agents (Part 1)</title><link>https://ethical.institute/blog/whose-memory-is-it-part-1/</link><guid isPermaLink="true">https://ethical.institute/blog/whose-memory-is-it-part-1/</guid><description>This is a 4-part series on how agents remember: building short-, medium- and long-term memory that scales across users, agents, and kubernetes clusters.</description><pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;LLMs are stateless by design, and without added memory logic every session starts from zero.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;A number of dedicated memory layers have emerged (and continue emerging almost daily) to tackle this, each with different approaches and tradeoffs. Which one should you adopt?&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Recently I spent some time extending the Kubernetes Agent Orchestration System (KAOS) to support multi-tiered memory persistence (aka short-, medium- and long-term memory). Along the way I hit most of the same issues that anyone would whilst building or integrating multi-tiered memory into an agentic system, so I thought it would be useful to compile all the learnings, design choices and examples into this 4-part series.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Hopefully this post is useful for anyone looking to do this on their own project. My objective:&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;Let’s make the memory layer BORING, so that the agents can continue to be the fun part.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;This first part includes the research findings from exploring ~30 tools, together with the taxonomy and the baseline implementations that motivate needing them, including tools like &lt;a href=&quot;https://github.com/mem0ai/mem0&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mem0&lt;/a&gt;, &lt;a href=&quot;https://github.com/getzep/graphiti&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Zep/Graphiti&lt;/a&gt;, &lt;a href=&quot;https://www.letta.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Letta (MemGPT)&lt;/a&gt;, &lt;a href=&quot;https://github.com/topoteretes/cognee&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Cognee&lt;/a&gt;, &lt;a href=&quot;https://github.com/memodb-io/memobase&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Memobase&lt;/a&gt;, &lt;a href=&quot;https://github.com/redis/agent-memory-server&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Redis Agent Memory Server&lt;/a&gt;, as well as native implementations in &lt;a href=&quot;https://openai.com/index/memory-and-new-controls-for-chatgpt/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI’s products&lt;/a&gt;, &lt;a href=&quot;https://claude.com/blog/memory&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Claude&lt;/a&gt;, &lt;a href=&quot;https://docs.langchain.com/oss/python/langgraph/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;LangGraph&lt;/a&gt;, &lt;a href=&quot;https://docs.crewai.com/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;CrewAI&lt;/a&gt;, and &lt;a href=&quot;https://google.github.io/adk-docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google ADK&lt;/a&gt;, among many others.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Throughout the series, I also share the learnings and best practices that came out of navigating through a large number of architecture tradeoffs, and getting my hands dirty on the implementation that now ships as a distributed, highly available, and scalable &lt;code&gt;MemoryStore&lt;/code&gt; resource that any agent can bind to.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As with my previous posts on &lt;a href=&quot;https://hackernoon.com/production-observability-for-multi-agent-ai-with-kaos-otel-signoz&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;observability for agentic systems&lt;/a&gt; and &lt;a href=&quot;https://hackernoon.com/autonomous-agentic-systems-a-practical-guide-to-always-on-agents&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;autonomous always-on agentic patterns&lt;/a&gt;, I will use KAOS as the concrete implementation example (concretely from Part 2, hands-on in Part 4), but the goal is to provide practical intuition for the primitives (tiers, scopes, folding, degradation), so that it applies whether you use KAOS, Mem0 directly, LangGraph, CrewAI, or a memory layer you wrote yourself.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This post is the first of a 4-part series, which we plan to release weekly over the next couple of weeks:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Part 1 (this post): What agent memory is and what to build on.&lt;/strong&gt; The taxonomy, the baseline implementations everyone starts with, and the engine landscape from surveying ~30 tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 2: Tiers and scopes for multi-tenant agents.&lt;/strong&gt; The three-tier design and the answer to whose memory it is (coming soon…).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 3: Memory as infrastructure.&lt;/strong&gt; The Kubernetes &lt;code&gt;MemoryStore&lt;/code&gt; resource, its deployment topology, and how to integrate it in your own agent (coming soon…).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 4: Agent memory in action.&lt;/strong&gt; A worked example that runs end to end on a secured cluster, with real outputs (coming soon…).&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;a-working-taxonomy-of-agent-memory&quot;&gt;A Working Taxonomy of Agent Memory&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;“Memory” is one of the most overloaded words in agentic systems, so it is worth separating it from the concepts it gets conflated with, such as:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;The &lt;strong&gt;context window&lt;/strong&gt;, which holds working state for a single model call.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session history&lt;/strong&gt;, which holds an auditable transcript of what was said.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prompt telemetry&lt;/strong&gt;, which holds the specific prompts relative to events in the system.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;To be more precise we can look at Princeton University’s paper on &lt;a href=&quot;https://arxiv.org/abs/2309.02427&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Cognitive Architectures for Language Agents (CoALA)&lt;/a&gt; to provide a more precise definition for “Memory” in agentic systems. We can define “Memory” as the component that holds the short-, medium- and long-term information an agent carries across turns and sessions to inform its reasoning.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This research paper quoted also provides a useful taxonomy for “memory types” that we will use to reason throughout the series, and especially in the tier design of part 2. This includes the memory types for episodic, semantic, procedural and temporal memory.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;These memory types are also mentioned in the Berkeley paper that released &lt;a href=&quot;https://arxiv.org/abs/2310.08560&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MemGPT&lt;/a&gt;, as well as how the Stanford paper on large-scale LLM simulations &lt;a href=&quot;https://arxiv.org/abs/2304.03442&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Generative Agents: Interactive Simulacra of Human Behavior&lt;/a&gt; structured their memory event stream.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The formal definition of these memory types (+ a few examples) is outlined as follows:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;


































&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Memory type&lt;/th&gt;&lt;th&gt;What it holds&lt;/th&gt;&lt;th&gt;Example&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Short-term (working)&lt;/td&gt;&lt;td&gt;Verbatim recent turns of the live conversation&lt;/td&gt;&lt;td&gt;“The user just said port 8080”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Episodic&lt;/td&gt;&lt;td&gt;Records of specific past events&lt;/td&gt;&lt;td&gt;“On Tuesday the deploy failed twice”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Semantic&lt;/td&gt;&lt;td&gt;Distilled, durable facts&lt;/td&gt;&lt;td&gt;“The user prefers blue-green deploys”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Procedural&lt;/td&gt;&lt;td&gt;Learned skills and how-tos&lt;/td&gt;&lt;td&gt;“Here is how we roll back this service”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Temporal&lt;/td&gt;&lt;td&gt;Facts with validity intervals&lt;/td&gt;&lt;td&gt;“Joe &lt;em&gt;was&lt;/em&gt; in a relationship until March, but not anymore.”&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;In practice what I found out however is that most frameworks only implement a small number of these, namely &lt;strong&gt;short-term&lt;/strong&gt; is always present, &lt;strong&gt;episodic and semantic&lt;/strong&gt; are bundled (the only difference is whether time is preserved), &lt;strong&gt;procedural&lt;/strong&gt; tends to be present mainly in coding agents (eg creating skills, commands, extensions), and &lt;strong&gt;temporal&lt;/strong&gt; tends to be replaced with “forgetting memory” functionality instead, or embedded with episodic/semantic.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;These appear more informally defined as:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Conversational continuity&lt;/strong&gt;: The agent remembers what was said three turns ago; a &lt;em&gt;same-session&lt;/em&gt; problem.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learned knowledge&lt;/strong&gt;: The agent remembers what it figured out last week; a &lt;em&gt;cross-session&lt;/em&gt; problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;For example, frameworks like &lt;a href=&quot;https://docs.langchain.com/oss/python/langgraph/persistence&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;LangGraph&lt;/a&gt; separate thread-scoped checkpointers from a cross-thread store. Another example is &lt;a href=&quot;https://docs.letta.com/guides/core-concepts/memory/memory-blocks&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Letta&lt;/a&gt;, which separates always-in-context memory blocks from an archival tier.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Most of the design mistakes I made early came from either trying to tackle all of these “memory-types” separately, by bundling sub-optimally, or by oversimplifying too much.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;But before we dive into the implementation, let’s cover the basics.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;memory-101-the-version-everyone-starts-with&quot;&gt;Memory 101: The Version Everyone Starts With&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Almost every agent system starts with the same memory implementation:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;memory &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handle_message&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(user_message):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    memory.append({&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: user_message})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    response &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run_agent(memory[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:], tools)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    memory.append({&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: response})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;And to be honest, the original KAOS memory was exactly this. It was an in-process queue with a max length, which ensured it was replaying the last N events into the next prompt.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The second version everyone builds is “just embed everything”:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handle_message&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(user_message):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    hits &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vector_store.search(embed(user_message), &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;top_k&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    context &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.join(h.text &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; h &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hits)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    response &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run_agent([context, user_message], tools)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vector_store.add(embed(user_message), user_message)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is better, but this is not memory in the form that we introduced eariler, it is just a better search mechanism across the prompt history.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Another tempting alternative as the next step is “context windows are huge now, just replay everything”.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;However this is not a great approach, and there are some benchmarks like &lt;a href=&quot;https://arxiv.org/abs/2410.10813&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;UCLA’s Bench on Long-Term Interactive Memory&lt;/a&gt;, which showed that models reasoning over full ~115K-token interaction histories lose 30-60% accuracy versus the same models given oracle retrieval.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If we look at it from a feature / functionality standpoint, we can summarise the gaps between the base and the production implementation as follows:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;




































&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Naive memory&lt;/th&gt;&lt;th&gt;Production memory&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Last-N turns, unbounded token growth&lt;/td&gt;&lt;td&gt;Token-budgeted window with principled eviction&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Verbatim replay of everything&lt;/td&gt;&lt;td&gt;Distilled facts, separated from the transcript (eg long- / short-term)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;One user, one process&lt;/td&gt;&lt;td&gt;Many tenants, many agents, many replicas&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Memory lives inside the agent pod&lt;/td&gt;&lt;td&gt;Memory survives restarts and is shared across the fleet&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Writes block the response&lt;/td&gt;&lt;td&gt;Extraction runs off the hot path&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Nothing is ever forgotten&lt;/td&gt;&lt;td&gt;Decay, retention, and right-to-erasure&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Memory failure crashes the turn&lt;/td&gt;&lt;td&gt;Memory failure degrades the turn&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case we can position “production memory” a tiered, scoped, context-specific and dynamic store, as opposed to purely a vector database connected to an agent.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Achieving this in a way that scales does get complex, as we need to decide who can see each memory tier, when we store facts, and how the agent behaves when memory fails.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;However now that we have the conceptual foundation in place, we can start looking at these functionalities relative to the frameworks available.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;choosing-an-engine-build-adopt-or-wrap&quot;&gt;Choosing an Engine: Build, Adopt, or Wrap&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Before designing anything, I surveyed the landscape thoroughly, assessing dozens of tools across three tiers, and we will cover the scope, approach and learnings in this section, starting with an overview of all the tiers as follows.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Tier 1: Dedicated memory frameworks.&lt;/strong&gt;
This tier encompasses purpose-built frameworks whose whole job is agent memory. From the longer list, we reduced it to the actively maintained ones:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;














































&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Candidate&lt;/th&gt;&lt;th&gt;Approach&lt;/th&gt;&lt;th&gt;Store&lt;/th&gt;&lt;th&gt;Strength&lt;/th&gt;&lt;th&gt;Weakness&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/mem0ai/mem0&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mem0&lt;/a&gt;&lt;/td&gt;&lt;td&gt;extracts facts from conversations into a vector store and recalls them by similarity&lt;/td&gt;&lt;td&gt;Qdrant, pgvector, others&lt;/td&gt;&lt;td&gt;most adopted, cleanest library integration&lt;/td&gt;&lt;td&gt;no OTel, tenant isolation only at application level&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/getzep/graphiti&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Zep / Graphiti&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds a temporal knowledge graph where facts carry validity intervals and provenance&lt;/td&gt;&lt;td&gt;Neo4j or FalkorDB&lt;/td&gt;&lt;td&gt;richest memory model, time-aware fact invalidation&lt;/td&gt;&lt;td&gt;heaviest to operate, costliest writes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/topoteretes/cognee&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Cognee&lt;/a&gt;&lt;/td&gt;&lt;td&gt;combines a knowledge graph with vector search, populated by an extract-and-load pipeline&lt;/td&gt;&lt;td&gt;LanceDB by default, Postgres or Neo4j optional&lt;/td&gt;&lt;td&gt;multi-tenancy and OTel built in&lt;/td&gt;&lt;td&gt;early stage, heavy dependencies, changing API&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/memodb-io/memobase&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Memobase&lt;/a&gt;&lt;/td&gt;&lt;td&gt;maintains structured user profiles and event timelines, with no embeddings on the hot path&lt;/td&gt;&lt;td&gt;Postgres + Redis&lt;/td&gt;&lt;td&gt;cheapest write path&lt;/td&gt;&lt;td&gt;profile-only recall, weak self-hosted multi-tenancy&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/redis/agent-memory-server&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Redis Agent Memory Server&lt;/a&gt;&lt;/td&gt;&lt;td&gt;serves two memory tiers (working and long-term) behind one REST API&lt;/td&gt;&lt;td&gt;Redis&lt;/td&gt;&lt;td&gt;the two-tier model mirrors what agents actually need&lt;/td&gt;&lt;td&gt;young project, no OTel&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;What this tier taught me is that the architectural differences are really differences in recall pattern and write cost. Vector-first designs answer “what do we know about X” cheaply, graph-first designs answer “how did this fact change over time” at the price of an LLM-heavy ingestion pipeline plus a graph database. The profile-first designs answer “who is this user” with no embeddings on the hot path at all, and the two-tier designs bake in the working-versus-long-term split directly.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;There were also clear shared gaps, mainly at the infrastructure level; none of them enforces tenant isolation below the application level, and almost none ships OpenTelemetry, so whichever one you pick, scope enforcement and observability become your integration work. That shared gap shaped the KAOS design more than any individual feature did.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It’s also worth noting that several of these libraries also offer an enterprise tier, so it was important to validate that basic features are not gated behind a paywall (similar to what we previously experienced with Google ADK and Vertex). More specifically &lt;a href=&quot;https://docs.mem0.ai/platform/platform-vs-oss&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mem0’s own platform-versus-OSS documentation&lt;/a&gt; gates temporal reasoning, memory decay, webhooks, export, analytics, and auto-scaling behind the managed platform, and &lt;a href=&quot;https://www.getzep.com/platform/graphiti/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Zep draws the line&lt;/a&gt; at governed multi-tenancy and compliance, with the OSS Graphiti engine giving you a single context graph to run yourself. The pattern across vendors is that the memory algorithms are open while the operational maturity is the commercial product, which previews the exact layer a platform adopting one of these engines has to build.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Tier 2. Agent frameworks with native memory.&lt;/strong&gt;
This tier encompasses the embedded memory functionality across end-to-end agentic frameworks, and included the usual suspect / popular frameworks like &lt;a href=&quot;https://docs.langchain.com/oss/python/langgraph/persistence&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;LangGraph’s Store and LangMem&lt;/a&gt;, &lt;a href=&quot;https://docs.crewai.com/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;CrewAI memory&lt;/a&gt;, &lt;a href=&quot;https://docs.llamaindex.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;LlamaIndex memory&lt;/a&gt;, &lt;a href=&quot;https://google.github.io/adk-docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google ADK&lt;/a&gt;’s MemoryService, and the &lt;a href=&quot;https://github.com/microsoft/agent-framework&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Microsoft Agent Framework&lt;/a&gt;. These were reviewed for their design choices, but adopting one for its memory means importing a second agent runtime next to your own, so they served as references and not as candidates.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The learning from this tier is actually what they all had in common. Every framework independently separates session-scoped state and cross-session knowledge, such as how LangGraph has thread-scoped checkpointers versus its cross-thread Store.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;There was also a clear separation between “local playground” and “production grade” when it comes to memory for all frameworks.&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.langchain.com/oss/python/langgraph/add-memory&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;LangGraph&lt;/a&gt;: In-memory store is for development, but it’s recommended to use a database-backed checkpointer and store for production.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://adk.dev/sessions/memory/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google ADK&lt;/a&gt;: Heavier paywall, as it only offers the &lt;code&gt;InMemoryMemoryService&lt;/code&gt; as open source, but anything serious would need to use Vertex AI.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/agent-framework/get-started/memory&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Microsoft Agent Framework&lt;/a&gt;: Defaults to an in-memory context provider, with durable state via first-party Cosmos checkpoint storage, and ships a first-party &lt;code&gt;Mem0ContextProvider&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;CrewAI: Community documented replacing its native store with Mem0 after hitting redeploy and user-isolation gaps.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Also interesting learnings from agent runtimes and coding agents:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openclaw.ai/reference/AGENTS.default&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenClaw&lt;/a&gt;: layers markdown memory files (&lt;code&gt;MEMORY.md&lt;/code&gt;, dated notes, per-skill &lt;code&gt;SKILL.md&lt;/code&gt;) and runs a “Skill Workshop” where the agent proposes new skills from successful conversations for human approval.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/skills.md&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hermes agent&lt;/a&gt;: Uses skills explicitly as procedural memory, which are auto-proposed after repeated successful tool-call patterns, carry semver versions bumped on each self-improvement, and follow an anti-sediment principle where a skill should get shorter and sharper over time.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Claude Code skills&lt;/a&gt;: Uses progressive disclosure, loading only ~100 tokens of skill metadata until a skill is triggered.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Native memory is increasingly an extensible interface where the shipped default is a placeholder, which means memory is being externalized by design across the ecosystem, and the dominant production pattern is framework plus engine. This is something that we had to take into consideration as well.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Tier 3. Managed and commercial services.&lt;/strong&gt;
This tier included commercial services with managed memory platforms, which provided insights on the broader design of the system and the interactions with the memory, as opposed to just the design of the memory capability itself. These included the &lt;a href=&quot;https://mem0.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mem0 Platform&lt;/a&gt;, &lt;a href=&quot;https://www.getzep.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Zep Cloud&lt;/a&gt;, &lt;a href=&quot;https://www.letta.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Letta Cloud&lt;/a&gt;, &lt;a href=&quot;https://openai.com/index/memory-and-new-controls-for-chatgpt/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI memory&lt;/a&gt;, and &lt;a href=&quot;https://docs.cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google’s Vertex Memory Bank&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The learnings from this tier were also quite helpful to understand some of the architectural and feature tradeoffs that were done at the platform level. Every managed platform has the same two-layer model: namely 1) an explicit, user-curated layer (eg. OpenAI’s saved memories, Claude’s editable memory summary) that is visible/available at the surface, and that is build on top of; 2) an automatically inferred and consolidated layer (eg. OpenAI’s chat-history reference, Vertex Memory Bank’s LLM extraction with per-scope deduplication and contradiction checks) where the memory store/retrieval algorithms live.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;There was however a clear distinction on the scope in which memory is available across each platform: For Claude, memory scope is per project, in Vertex scope is per identity with configurable memory “topics”, and Zep scopes per subject graph. None of them defaults to one global memory per account, which makes it clear that there is a design decision required on the isolation boundary.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;conclusions-from-surveying-the-ecosystem&quot;&gt;Conclusions from Surveying the Ecosystem&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Given the review was done in context of KAOS, the lens / considerations through which these were reviewed included the following non-exhaustive list:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Long-term capability coverage&lt;/li&gt;
&lt;li&gt;Retrieval quality&lt;/li&gt;
&lt;li&gt;Embeddability as a library&lt;/li&gt;
&lt;li&gt;Pluggable storage backends&lt;/li&gt;
&lt;li&gt;Infrastructure delta / overhead&lt;/li&gt;
&lt;li&gt;Multi-tenancy hooks&lt;/li&gt;
&lt;li&gt;Observability&lt;/li&gt;
&lt;li&gt;Licensing&lt;/li&gt;
&lt;li&gt;Maturity&lt;/li&gt;
&lt;li&gt;Write-path cost&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Based on these, the library that clearly stood out was &lt;strong&gt;Mem0&lt;/strong&gt;. At least at the time of writing, Mem0 maximized the features and capabilities with the lowest integration friction. Mem0 also has the strongest ecosystem maturity, and pluggable stores.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It’s however worth noting that despite Mem0 being the right choice for this context, one learning that may seem obvious in retrospect was that &lt;strong&gt;there is no “Perfect Candidate”.&lt;/strong&gt; The graph-first leaders (Graphiti, Cognee) have the most features but at the highest cost. Low-delta options (Redis AMS) buy fit at maturity cost. Building it yourself directly on the raw vector or graph stores, which we also weighed as the baseline option, allows you to have all the features and fit, but at the cost of rebuilding mature extraction and retrieval that already exists under permissive licenses.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This also applies to the numbers the frameworks publish about themselves. Interestingly enough, Mem0’s own research supports that extraction-based memory improves latency and cost, however it does not improve raw accuracy: in &lt;a href=&quot;https://arxiv.org/abs/2504.19413&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mem0’s own evaluation&lt;/a&gt; on LoCoMo, a full-context baseline beats Mem0 on raw accuracy (72.9% vs 66.9%), while memory buys a 91% cut in p95 latency (1.44s vs 17.1s) and over 90% fewer tokens per conversation. At fleet scale that trade is exactly right, since you cannot ship 17-second turns and 26K-token replays, but it is a trade you should make knowingly.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As part of this, despite Mem0 being the strongest choice, it became clear that &lt;strong&gt;adopting a memory engine means choosing which 60% of the system you do not have to build, and committing to build the remaining 40% around it&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For Mem0, this meant working on the bridge to close some of the gaps, particularly at the infrastructure and interoperability layer. These included:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Enabling telemetry by instrumenting every operation and ensure correlation+consistency with the broader KAOS telemetry.&lt;/li&gt;
&lt;li&gt;Introduce tenant isolation, as this is enforced at the Mem0 application level, so enforce scope through the memory service.&lt;/li&gt;
&lt;li&gt;Bundle up the kubernetes packaging to ensure high availability and scalability as a distributed service.&lt;/li&gt;
&lt;li&gt;Bridge the short- and medium-term memory with a native integration with the Pydantic AI server that we have built as part of KAOS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Each of these gaps becomes a design decision in parts 2 and 3.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Based on these initial decisions we were able to proceed to the architecture of the memory system itself, which is exactly where part 2 picks up.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;closing-thoughts-for-part-1&quot;&gt;Closing Thoughts for Part 1&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;This first part covered the ground you need before writing any memory code with a working taxonomy that separates memory from the context window and the session transcript. We also reviewed the baseline implementations and the understood some of the limitations. This included the survey of the memory engine landscape, and the thinking process that went into selecting the memory framework to build upon.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;However this is only the beginning as choosing the memory framework is only 40% of the work, we still need to build the remaining 60% to ensure we can integrate it in a coherent and scalable way for our distributed agent system use-case.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In part 2 we take that position and design the memory system itself. This includes the three tiers that separate “memory tiers”, and the scope model that answers the title’s question of “whose memory is it?”. Stay tuned, part 2&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;The series:&lt;/strong&gt;&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Part 1 (this post): What agent memory is and what to build on.&lt;/li&gt;
&lt;li&gt;Part 2: Tiers and scopes for multi-tenant agents (coming soon…).&lt;/li&gt;
&lt;li&gt;Part 3: Memory as infrastructure (coming soon…).&lt;/li&gt;
&lt;li&gt;Part 4: Agent memory in action (coming soon…).&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded><category>agents</category><category>memory</category><category>kubernetes</category></item><item><title>Autonomous Agentic Systems: A Practical Guide to Always-On Agents</title><link>https://ethical.institute/blog/autonomous-agentic-systems-always-on-agents/</link><guid isPermaLink="true">https://ethical.institute/blog/autonomous-agentic-systems-always-on-agents/</guid><description>A practical guide to designing, operating and scaling always-on agents, from basic agentic loops to scalable autonomous agentic systems.</description><pubDate>Mon, 01 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;The pattern of “always-on” autonomous agents that work proactively in the background has been taking over the agentic systems space.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This pattern was launched to massive popularity by &lt;a href=&quot;https://clawdocs.org/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenClaw&lt;/a&gt;, as it basically moved the field away from purely Chat-based interactions (aka request-response), and towards agents that proactively take over tasks autonomously in the background (aka an infinite loop).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is an interesting new architectural innovation which has set a clear path where agentic systems are heading towards:&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;24/7 agents with a &lt;a href=&quot;https://clawdocs.org/architecture/heartbeat?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;heartbeat-style loop&lt;/a&gt; that keeps checking the world even when you are not prompting it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;And although OpenClaw was one of the first movers, the rest of the frameworks have also followed (+ catching up): &lt;a href=&quot;https://docs.langchain.com/oss/python/langgraph/overview?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;LangGraph&lt;/a&gt;, &lt;a href=&quot;https://docs.crewai.com/introduction?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;CrewAI&lt;/a&gt;, &lt;a href=&quot;https://openai.github.io/openai-agents-python/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI Agents SDK&lt;/a&gt;, &lt;a href=&quot;https://google.github.io/adk-docs/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google ADK&lt;/a&gt;…&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;…and as part of this trend, we also ventured into the world of autonomous agentic systems at scale, learning from implementing autonomous agentic loops in Kubernetes in KAOS - this led us through the good, the bad and the ugly of autnomous agent patterns.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this post we want to share the learnings designing, developing and scaling autonomous agentic patterns, including what actually changes when an agentic loop becomes an autonomous workload, and why Kubernetes starts to become relevant once you need to orchestrate many of them.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;the-useful-part-of-the-hype&quot;&gt;The Useful Part of the Hype&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;The phrase “autonomous agent” is overloaded enough to be almost useless.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://www.anthropic.com/research/building-effective-agents?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Anthropic’s guidance on building effective agents&lt;/a&gt; makes a useful distinction between workflows with predefined code paths and agents where the LLM dynamically directs its own process and tool usage.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For a broader research view, recent surveys of &lt;a href=&quot;https://arxiv.org/abs/2308.11432?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;LLM-based autonomous agents&lt;/a&gt; and &lt;a href=&quot;https://arxiv.org/abs/2309.07864?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;large language model based agents&lt;/a&gt; cover the recurring architecture pieces: memory, planning, action, tools, and evaluation.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Sometimes it may mean “a chatbot that keeps working in the background”. Sometimes it may mean “a stateful graph workflow”. And sometimes it just means “we put &lt;code&gt;while True&lt;/code&gt; around the model call”.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;But there is a useful distinction here - a normal tool-using agent is usually request/response:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;User asks a question.&lt;/li&gt;
&lt;li&gt;Agent calls the model.&lt;/li&gt;
&lt;li&gt;Model decides whether to use tools.&lt;/li&gt;
&lt;li&gt;Tools return data.&lt;/li&gt;
&lt;li&gt;Agent returns an answer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;An autonomous agent in the context of this post, ignores whether a human is waiting on the other side of the HTTP response.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The work may continue; the environment may change; the agent may run again; it may call tools repeatedly; it may need to remember what happened last time.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The hard part is not making the model call itself again (aka the loop).&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;The hard part is making that agentic loop safe to run when nobody is staring at the chat.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;ai-agents-101-the-loop-everyone-starts-with&quot;&gt;AI Agents 101: The Loop Everyone Starts With&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Most agent systems begin with a deceptively simple loop:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; run_agent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(messages, tools, max_steps&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; step &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(max_steps):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        response &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.chat(messages, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tools)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.tool_calls:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; call &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.tool_calls:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tools[call.name](&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;call.arguments)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                messages.append({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;tool_call_id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: call.id,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: result,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            continue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    raise&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; RuntimeError&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;agent exceeded max_steps&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is the core pattern behind a lot of the current wave of agentic software, and it maps closely to the reasoning/action loop described in &lt;a href=&quot;https://arxiv.org/abs/2210.03629?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ReAct&lt;/a&gt; and the broader tool-use direction represented by &lt;a href=&quot;https://arxiv.org/abs/2302.04761?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Toolformer&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This loop is powerful, but it is still usually bounded by a synchronous request/response paradigm.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;what-changes-when-the-loop-keeps-running&quot;&gt;What Changes When the Loop Keeps Running?&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;The naive autonomous version looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; run_autonomous&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(goal, tools, interval_seconds&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;60&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    memory &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        messages &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;You are an autonomous worker.&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: goal},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;memory[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        response &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run_agent(messages, tools)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        memory.append({&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: response})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sleep(interval_seconds)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is useful as a mental model (but not something I would want to deploy yet).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once the loop runs without a synchronous caller, the engineering problem changes:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;
































&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Request/response agent&lt;/th&gt;&lt;th&gt;Autonomous agent&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;User waits for an answer&lt;/td&gt;&lt;td&gt;Work continues after the caller leaves&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Loop ends with a response&lt;/td&gt;&lt;td&gt;Loop may run periodically or indefinitely&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Failure is a request error&lt;/td&gt;&lt;td&gt;Failure becomes an operational incident&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Context can be request-local&lt;/td&gt;&lt;td&gt;Needs task state, memory, and persistence boundaries&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tool calls happen inside one request&lt;/td&gt;&lt;td&gt;Tool calls may become ongoing side effects&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Debugging starts with one trace&lt;/td&gt;&lt;td&gt;Debugging starts with task history, memory, state, and logs&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is the main thesis:&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;Autonomy is not the loop. Autonomy is the operating model &lt;strong&gt;around&lt;/strong&gt; the loop.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;the-missing-primitive-a-unit-of-agent-work&quot;&gt;The Missing Primitive: A Unit of Agent Work&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;If the agent can keep working after the caller leaves, this is where we start the need to introduce an ability to reason around the tasks being performed.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The simplest form is something as simple as:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; TaskState&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Enum&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    SUBMITTED&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;submitted&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    WORKING&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;working&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    COMPLETED&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;completed&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    FAILED&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;failed&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    CANCELED&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;canceled&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@dataclass&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    goal: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    state: TaskState&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    output: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    history: list[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;dict&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; field(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;default_factory&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;list&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    events: list[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;dict&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; field(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;default_factory&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;list&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is indeed not an AI breakthrough… it’s ordinary distributed-systems plumbing.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Production autonomous agents inherit all the boring concerns that make systems operable:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;submission,&lt;/li&gt;
&lt;li&gt;lifecycle state,&lt;/li&gt;
&lt;li&gt;output capture,&lt;/li&gt;
&lt;li&gt;error reporting,&lt;/li&gt;
&lt;li&gt;cancellation,&lt;/li&gt;
&lt;li&gt;retention,&lt;/li&gt;
&lt;li&gt;auditing,&lt;/li&gt;
&lt;li&gt;ownership.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;If a user starts a long-running research task and closes the browser, they need a task ID. If an agent monitors a Kubernetes namespace, an operator needs to know whether it is working, stuck, failed, or canceled. If a tool starts returning bad data, you need to know which tasks used it.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The &lt;a href=&quot;https://a2a-protocol.org/latest/specification/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;A2A protocol specification&lt;/a&gt; similarly treats a task as the fundamental unit of work for long-running agent interaction - and this is a good place to start.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;budgets-are-not-just-about-cost&quot;&gt;Budgets Are Not Just About Cost&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;The first reason people add budgets is usually cost. But budgets are also safety controls, especially given the risks OWASP groups under &lt;a href=&quot;https://owasp.org/www-project-top-10-for-large-language-model-applications/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;excessive agency in LLM applications&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;




























&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Budget&lt;/th&gt;&lt;th&gt;What it bounds&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;max iterations&lt;/td&gt;&lt;td&gt;runaway reasoning loops&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;max runtime&lt;/td&gt;&lt;td&gt;stuck or excessively long work&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;max tool calls&lt;/td&gt;&lt;td&gt;API pressure and side effects&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;token/cost budget&lt;/td&gt;&lt;td&gt;spend and context growth&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;per-iteration timeout&lt;/td&gt;&lt;td&gt;one blocked tool/model call&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;A minimal check can be as simple as:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; budget_exhausted&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(budgets, started_at, iteration, tool_calls):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; budgets.max_iterations &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; iteration &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; budgets.max_iterations:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;max_iterations&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; budgets.max_runtime_seconds &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; time.monotonic() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; started_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; budgets.max_runtime_seconds:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;max_runtime_seconds&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; budgets.max_tool_calls &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tool_calls &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; budgets.max_tool_calls:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;max_tool_calls&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; None&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;why-openclaw-langgraph-crewai-adk-and-the-others-point-in-the-same-direction&quot;&gt;Why OpenClaw, LangGraph, CrewAI, ADK and the Others Point in the Same Direction&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;OpenClaw’s design pattern is meant to keep a private, self-hosted agent running with memory, integrations, skills, and a heartbeat. Let’s have a look at how other frameworks approach it:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;
































&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Framework&lt;/th&gt;&lt;th&gt;Approach&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://docs.langchain.com/oss/python/langgraph/overview?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;LangGraph&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Durable, stateful agent orchestration.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://docs.crewai.com/introduction?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;CrewAI&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Crews, flows, memory, guardrails, and human-in-the-loop controls&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openai.github.io/openai-agents-python/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI Agents SDK&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Gives developers a managed loop with sessions.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://google.github.io/adk-docs/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google ADK&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Frames the problem around production agents, graph workflows, evaluation, debugging, context management, and deployment&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/semantic-kernel/overview/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Semantic Kernel&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Brings the same agent/tool orchestration pattern into Microsoft’s enterprise application ecosystem&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://microsoft.github.io/autogen/stable/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AutoGen&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Extends Microsoft Research’s multi-agent conversation work into an official framework&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;The abstractions and approaches are different in some cases, but the same primitives keep reappearing in the source code implementation, including:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;state&lt;/li&gt;
&lt;li&gt;tools&lt;/li&gt;
&lt;li&gt;memory&lt;/li&gt;
&lt;li&gt;guardrails&lt;/li&gt;
&lt;li&gt;tracing&lt;/li&gt;
&lt;li&gt;human intervention&lt;/li&gt;
&lt;li&gt;deployment&lt;/li&gt;
&lt;li&gt;resumability&lt;/li&gt;
&lt;li&gt;task control&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once agents stop being one-off prompt handlers, frameworks have to become work managers. They need to manage units of agent work, not just model calls. And when we have to take it to the next level of scale, this is where things get more complicated…&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;kubernetes-enters-the-picture&quot;&gt;Kubernetes Enters the Picture&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;A platform cannot guarantee that the model will reason correctly. But if we have a way in which we can abstract some of these complex agentic concepts into architectural abstractions, we can then answer practical questions that become unavoidable when you run many agents:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Where does each agent run?&lt;/li&gt;
&lt;li&gt;What identity does it have?&lt;/li&gt;
&lt;li&gt;Which tools can it reach?&lt;/li&gt;
&lt;li&gt;Which secrets can it read?&lt;/li&gt;
&lt;li&gt;What network is it allowed to access?&lt;/li&gt;
&lt;li&gt;How do we restart it?&lt;/li&gt;
&lt;li&gt;How do we observe it?&lt;/li&gt;
&lt;li&gt;How do we isolate it?&lt;/li&gt;
&lt;li&gt;How do we scale it?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://kubernetes.io/blog/2026/03/20/running-agents-on-kubernetes-with-agent-sandbox/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AI workloads are moving away from short-lived stateless requests&lt;/a&gt;, and more toward coordinated agents that run constantly, maintain context, use tools, execute code, and communicate over longer periods.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If OpenClaw is one vision of the always-on agent, Kubernetes is one answer to the fleet question:&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;What happens when every team, service, workflow, or tenant wants its own autonomous agents?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;At that point you need scheduling, identity, isolation, policy, rollouts, configuration, and observability. Basically we need the same things we already learned to need for microservices, except the workload is now non-deterministic, tool-using, and stateful. Kubernetes already has much of this substrate through the &lt;a href=&quot;https://kubernetes.io/docs/concepts/extend-kubernetes/operator/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Operator pattern&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/reference/access-authn-authz/rbac/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;RBAC&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/concepts/services-networking/network-policies/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NetworkPolicy&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;HPA&lt;/a&gt;, and event-driven scaling systems like &lt;a href=&quot;https://keda.sh/docs/2.16/concepts/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;KEDA&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We made infrastructure much harder again. Let’s now make it simpler.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;scaling-your-agentic-kaos&quot;&gt;Scaling Your Agentic KAOS&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;To make this less abstract, let’s dive into it with a Kubernetes example using &lt;a href=&quot;https://ai.pydantic.dev/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pydantic AI&lt;/a&gt; and &lt;a href=&quot;https://hackernoon.com/production-observability-for-multi-agent-ai-with-kaos-otel-signoz?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;KAOS&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://github.com/axsaucedo/kaos?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;KAOS is a Kubernetes-native agent orchestration framework&lt;/a&gt;. It defines agents, &lt;a href=&quot;https://modelcontextprotocol.io/introduction?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MCP&lt;/a&gt; tool servers, and model APIs as Kubernetes resources. The most recent learnings are shared from the implementation of the new autonomous/&lt;a href=&quot;https://a2a-protocol.org/latest/specification/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;A2A&lt;/a&gt; milestone, which supports asynchronous task lifecycle, JSON-RPC task methods, autonomous self-looping execution, budgets, cancellation, task history, CLI/UI debugging, and examples.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We’ll cover it with a fun example, where we’ll have a Production Operations Agent which will monitor a Kubernetes cluster - namely this will include:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;an agent with a monitoring goal,&lt;/li&gt;
&lt;li&gt;a read-only Kubernetes service account,&lt;/li&gt;
&lt;li&gt;an MCP server exposing Kubernetes tools,&lt;/li&gt;
&lt;li&gt;a reporting tool,&lt;/li&gt;
&lt;li&gt;a model API,&lt;/li&gt;
&lt;li&gt;budgets and task controls,&lt;/li&gt;
&lt;li&gt;an endpoint for async task interaction.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;The key part of the Agent configuration looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;kaos.tools/v1alpha1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Agent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;cluster-monitor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  modelAPI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;monitor-modelapi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  model&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;smollm2:135m&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  mcpServers&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;monitor-k8s-mcp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;monitor-report-mcp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    description&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Autonomous cluster monitoring agent&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    instructions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      You are a Kubernetes cluster monitoring agent.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      List pods, check status, and generate a health report.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    autonomous&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      goal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Monitor the Kubernetes cluster health. List pods, check their status, and generate a health report.&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      intervalSeconds&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;60&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      maxIterRuntimeSeconds&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;120&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    taskConfig&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      maxIterations&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      maxRuntimeSeconds&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;300&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      maxToolCalls&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;These are some of the key configurations:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;autonomous.goal&lt;/code&gt; defines the persistent objective.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;intervalSeconds&lt;/code&gt; controls the loop cadence.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;maxIterRuntimeSeconds&lt;/code&gt; bounds one iteration.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;taskConfig&lt;/code&gt; gives bounded defaults for async tasks.&lt;/li&gt;
&lt;li&gt;MCP servers define the tools.&lt;/li&gt;
&lt;li&gt;Kubernetes RBAC defines what those tools can actually access.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-01.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 1: Alejandro Saucedo&amp;#x27;s image-fa0a1&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Monitoring is a good use-case for autonomous agents as the goal persists over time, the environment changes, and the agent needs tools but should be heavily constrained.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For the full end-to-end example, including the MCP Servers and Cluster RBAC, you can try it yourself in &lt;a href=&quot;https://axsaucedo.github.io/kaos/v0.4.6/examples/autonomous-agent.html?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the hands on KAOS example section&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;continuous-mode-vs-async-task-mode&quot;&gt;Continuous Mode vs Async Task Mode&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Another design decision that we had to come across which was interesting was the distinction between “continuous autonomous execution” and “async task execution”.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;“Continuous mode” does what it suggests, runs in the background with a goal, and infinitely iterates towards that goal: i.e. when the pod starts, it begins working toward that goal. In this case it is daemon-like: monitoring, checking, reporting, maintaining, watching.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;“Async task mode” is the superset capability that allows the framework to execute without user / API interaction once the task is submitted; it would just not loop once the goal is achieved or the budgets are depleted.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For an example of an Async task, a caller sends a task, gets a task ID, and the agent continues working in the background.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The caller can later inspect or cancel it, which maps to the async task model in the &lt;a href=&quot;https://a2a-protocol.org/latest/specification/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;A2A protocol&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;jsonrpc&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;method&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;SendMessage&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;params&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;message&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;parts&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          &quot;text&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Research recent autonomous agent frameworks and summarize findings.&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;configuration&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;mode&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;autonomous&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Through the KAOS CLI, that becomes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; a2a&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; send&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; researcher&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  --message&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Research recent autonomous agent frameworks and summarize findings.&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  --async&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Then the caller can poll:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;jsonrpc&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;method&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;GetTask&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;params&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;task_abc123&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Or cancel:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;jsonrpc&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;method&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;CancelTask&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;params&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;task_abc123&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;task-state-is-not-memory&quot;&gt;Task State Is Not Memory&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Another small but important lesson that we had to reason about was that task state and memory are not the same thing; this is obvious when saying it out-loud, but it was important to figure out what we need to have available where for the agent framework to have the right context. This distinction lines up with agent research that treats memory and reflection as part of the agent’s internal execution context, such as &lt;a href=&quot;https://arxiv.org/abs/2303.11366?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Reflexion&lt;/a&gt; and &lt;a href=&quot;https://arxiv.org/abs/2304.03442?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Generative Agents&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We found that task state should be small and stable:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;submitted,&lt;/li&gt;
&lt;li&gt;working,&lt;/li&gt;
&lt;li&gt;completed,&lt;/li&gt;
&lt;li&gt;failed,&lt;/li&gt;
&lt;li&gt;canceled,&lt;/li&gt;
&lt;li&gt;budget exhausted.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Memory can be richer:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;user messages,&lt;/li&gt;
&lt;li&gt;agent responses,&lt;/li&gt;
&lt;li&gt;tool calls,&lt;/li&gt;
&lt;li&gt;tool results,&lt;/li&gt;
&lt;li&gt;delegations,&lt;/li&gt;
&lt;li&gt;observations,&lt;/li&gt;
&lt;li&gt;session history.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you mix them, your task API becomes noisy and your memory system becomes responsible for lifecycle control (which is not what anyone would want).&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;debugging-many-autonomous-agents&quot;&gt;Debugging Many Autonomous Agents&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;The debugging story changes as soon as the work is no longer attached to one waiting user - everything gets exponentially harder.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You need to answer:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;What task did the agent start?&lt;/li&gt;
&lt;li&gt;Is the agent still running?&lt;/li&gt;
&lt;li&gt;What did the agent do?&lt;/li&gt;
&lt;li&gt;Which tools did the agent call?&lt;/li&gt;
&lt;li&gt;What did those tools return?&lt;/li&gt;
&lt;li&gt;Did the agent hit a budget?&lt;/li&gt;
&lt;li&gt;Can I stop the agent?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;We had to think about those questions and expose abstractions to support on those workflows; with KAOS these are through CLI and UI:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; a2a&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; send&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;agen&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --message&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;...&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --async&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; a2a&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;agen&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --task-id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; a2a&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; cancel&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;agen&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --task-id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The UI adds also agent-card inspection, SendMessage, task viewer, auto-polling, cancellation, task history, and memory conversation views. At the telemetry layer, the &lt;a href=&quot;https://opentelemetry.io/docs/specs/semconv/gen-ai/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenTelemetry GenAI semantic conventions&lt;/a&gt; now define model and agent spans that are directly relevant for debugging these systems.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;how-you-could-build-the-basics-yourself&quot;&gt;How You Could Build the Basics Yourself&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;You do not need a full framework to understand the minimal shape, we can start with a single-iteration primitive:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; run_agent_once&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(goal, history) -&gt; tuple[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    messages &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; build_messages(goal, history)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    response &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run_agent(messages, tools)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.text, response.tool_call_count&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Then wrap it in the smallest useful control loop:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; run_autonomous_task&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(task, budgets, cancel_event):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    started_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; time.monotonic()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    iteration &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    tool_calls &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    task.state &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TaskState.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;WORKING&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cancel_event.is_set():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            task.state &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TaskState.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CANCELED&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        reason &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; budget_exhausted(budgets, started_at, iteration, tool_calls)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; reason:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            task.events.append({&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;budget.exhausted&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;reason&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: reason})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            task.state &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TaskState.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;COMPLETED&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        output, calls &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run_agent_once(task.goal, task.history)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        task.output &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; output&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        task.history.append({&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;iteration&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: iteration, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;output&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: output})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tool_calls &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; calls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        iteration &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; calls &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            task.state &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TaskState.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;COMPLETED&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is not production-ready: i.e it does not handle persistence, retries, distributed workers, authentication, policy, observability, or recovery after process restart. However it shows the skeleton:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;task identity,&lt;/li&gt;
&lt;li&gt;state transitions,&lt;/li&gt;
&lt;li&gt;budgets,&lt;/li&gt;
&lt;li&gt;cancellation,&lt;/li&gt;
&lt;li&gt;output,&lt;/li&gt;
&lt;li&gt;history,&lt;/li&gt;
&lt;li&gt;completion detection.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you use an existing framework, look for where these pieces live.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;when-not-to-make-your-agents-autonomous&quot;&gt;When Not to Make Your agents Autonomous&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;There is a temptation to turn every useful agent into a background process. Anthropic’s advice is a useful counterweight here: start with the simplest solution possible, and only increase agentic complexity when it is needed.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Autonomy is helpful when:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;the environment changes over time&lt;/li&gt;
&lt;li&gt;the goal persists beyond one request&lt;/li&gt;
&lt;li&gt;the work is too long for a synchronous response&lt;/li&gt;
&lt;li&gt;the agent can safely observe or act with scoped tools&lt;/li&gt;
&lt;li&gt;the user benefits from periodic or event-driven progress&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Autonomy is not helpful when:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;the action is high-risk and lacks approval controls&lt;/li&gt;
&lt;li&gt;tool permissions are broad or unclear&lt;/li&gt;
&lt;li&gt;success criteria are vague&lt;/li&gt;
&lt;li&gt;cancellation is missing&lt;/li&gt;
&lt;li&gt;progress cannot be inspected&lt;/li&gt;
&lt;li&gt;cost or side effects are unbounded&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Those risks also show up in more formal governance and security guidance, including the &lt;a href=&quot;https://airc.nist.gov/AI_RMF_Knowledge_Base/AI_RMF?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NIST AI Risk Management Framework&lt;/a&gt; and the OWASP LLM Top 10 category of excessive agency.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;lessons-for-production-autonomous-agents&quot;&gt;Lessons for Production Autonomous Agents&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;To wrap up, I want to share a few set of learnings / patterns I would carry into any autonomous-agent system.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-start-with-the-loop-but-design-the-task-contract-early&quot;&gt;1. Start with the loop, but design the task contract early&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The agentic loop is the easy part to prototype, however the task contract is what makes it operable.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-separate-continuous-autonomy-from-bounded-background-work&quot;&gt;2. Separate continuous autonomy from bounded background work&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;An agent that monitors forever and an agent that writes a report in the background need different controls.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-treat-budgets-as-safety-controls&quot;&gt;3. Treat budgets as safety controls&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Budgets bound cost, time, tool side effects, API pressure, and runaway reasoning.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;4-keep-task-state-separate-from-memory&quot;&gt;4. Keep task state separate from memory&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Task state is the external lifecycle, memory is the execution context, and mixing them makes APIs noisy and debugging harder.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;5-scope-tools-with-permissions&quot;&gt;5. Scope tools with permissions&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Autonomy becomes risky through tools, ensure you support this with read-only service accounts, scoped roles, network policy, and secret boundaries matter more than the prompt. This is where Kubernetes &lt;a href=&quot;https://kubernetes.io/docs/reference/access-authn-authz/rbac/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;RBAC&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/concepts/services-networking/network-policies/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NetworkPolicy&lt;/a&gt;, and &lt;a href=&quot;https://owasp.org/www-project-top-10-for-large-language-model-applications/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OWASP’s LLM security guidance&lt;/a&gt; become more important than prompt wording.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;6-build-cancellation-into-the-first-version&quot;&gt;6. Build cancellation into the first version&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Cancellation is not an advanced feature, it is a foundational feature that should be integrated by design.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;7-use-kubernetes-for-workload-concerns-not-reasoning-quality&quot;&gt;7. Use Kubernetes for workload concerns, not reasoning quality&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Kubernetes can help with lifecycle, identity, permissions, isolation, networking, rollouts, and observability - but it will not make a bad model / agent less bad. The Kubernetes &lt;a href=&quot;https://kubernetes.io/blog/2026/03/20/running-agents-on-kubernetes-with-agent-sandbox/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Agent Sandbox&lt;/a&gt; work is an example of the same platform question being addressed with agent-specific workload primitives.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;8-instrument-everything&quot;&gt;8. Instrument everything&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Agent loops are variable, non-deterministic, and tool-heavy: Traces, logs, metrics, task IDs, and memory events are how you understand them later. The &lt;a href=&quot;https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-agent-spans/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenTelemetry GenAI agent spans&lt;/a&gt; and &lt;a href=&quot;https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;model spans&lt;/a&gt; are useful standards to track here. This is something that we skimmed through in this post, if you are interested on a more in-depth post on this you should check out: &lt;a href=&quot;https://hackernoon.com/production-observability-for-multi-agent-ai-with-kaos-otel-signoz?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Monitoring KAOS: Observability for Multi-Agent Systems&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;</content:encoded><category>agents</category><category>agentic-systems</category><category>kubernetes</category></item><item><title>Production Observability for Multi-Agent AI (with KAOS + OTel + SigNoz)</title><link>https://ethical.institute/blog/production-observability-multi-agent-ai/</link><guid isPermaLink="true">https://ethical.institute/blog/production-observability-multi-agent-ai/</guid><description>A practical guide to adding production-grade observability to multi-agent AI systems with the K8s Agent Orchestration System using OpenTelemetry and SigNoz.</description><pubDate>Thu, 05 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;You’ve built an AI agent that works in your laptop. It automatically chains tools together, delegates tasks to specialist sub-agents, and produces sound results.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Then you deploy it to production:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;A user reports that a request “took forever”.&lt;/li&gt;
&lt;li&gt;Another says they got a strange response.&lt;/li&gt;
&lt;li&gt;Your logs show the agent ran&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;But, what happened in those 45 seconds between request and response?&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Welcome to the &lt;strong&gt;observability challenge of agentic systems.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;“Traditional logs tell you that it ran. Observability tells you why it ran like that.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this article, we’ll walk through a complete end-to-end example of observability for multi-agent systems.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Below is a preview of the multi-agent system that we’ll analyse, monitor and diagnose in this post:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-01.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 1: The multi-agent system that we will monitoring&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;The multi-agent system that we will monitoring&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s start with the main question of…&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;why-do-multi-agent-systems-need-different-observability&quot;&gt;…Why do Multi-Agent Systems Need (Different) Observability?&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Traditional microservices have predictable patterns: a request comes in, some processing happens, a response goes out. Latency is relatively consistent, code paths are deterministic, and debugging usually involves tracing a single thread of execution.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;its-not-just-a-request-response&quot;&gt;It’s Not Just a Request-Response&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Agentic systems break traditional assumptions:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;




























&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Traditional API&lt;/th&gt;&lt;th&gt;Agentic System&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Synchronous request-response&lt;/td&gt;&lt;td&gt;Iterative reasoning loops&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Predictable latency (50-500ms)&lt;/td&gt;&lt;td&gt;Variable: 100ms to 60+ seconds&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Deterministic code paths&lt;/td&gt;&lt;td&gt;Non-deterministic LLM decisions&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Single service per request&lt;/td&gt;&lt;td&gt;Model calls + tool calls + delegations&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fixed cost per request&lt;/td&gt;&lt;td&gt;Cost varies by token usage&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;ai-agents-101-the-agentic-loop&quot;&gt;&lt;strong&gt;AI Agents 101: The Agentic Loop&lt;/strong&gt;&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Consider the core loop of a multi-AI agent system. This is the deceptively simple pattern that has led to the current wave of innovation in AI systems.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Below is a simplified agentic loop as we skip a lot of the nuances, but the idea is that we send a first call for the LLM to respond with tool calls or delegation calls, and if there’s none or we run into the max steps, then we send the final response.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; process_message&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, messages):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; step &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.max_steps):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # 1. Call the LLM specifically for tool/delegation requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        response &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.model.process_tool_request(messages)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # 2. If the model wants to use a tool, execute it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.has_tool_call:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.execute_tool(response.tool_call)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            messages.append({&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: result})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            continue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # 3. If the model wants to delegate, call another agent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        elif&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.needs_delegation:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.delegate_to_agent(response.delegation)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            messages.append({&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: result})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            continue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;            # If no tools/delegations we move to final answer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            break&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # 4. We return our final answer with any context gathered&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.model.process_final_answer(messages)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;As we can see, each iteration of this loop may take a different path. The model might need one tool call or five.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It might delegate to one sub-agent or chain through three. Traditional logging (e.g. “request started” … “request completed”) tells you almost nothing about what actually happened.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;And once we take this into a distributed system it gets even more complex to understand what is going on - as we will see in this post.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In the last section of this post we will show you also how we will instrument this agentic loop specifically as well.&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;We’ve replaced ‘request-response’ with ‘request—panic—tool—panic—delegate—panic—response’.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;the-three-pillars-of-agent-observability&quot;&gt;The Three Pillars of Agent Observability&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;OpenTelemetry provides three types of telemetry data, each serving a distinct purpose for agentic systems.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Traces&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The trace hierarchy maps directly to what the agent did, capturing and connecting every hop across the journey.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HTTP&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; POST&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chat&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;completions (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15.&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;2s&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; total)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; agent.agentic_loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;    -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; agent.step.1 (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;1s&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;        -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.inference (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;0s&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;    -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; agent.step.2 (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8.&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;5s&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;        -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model.inference (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;1s&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;        -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tool.web_search (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6.&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;3s&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Here may be your bottleneck&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;    -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; agent.step.3 (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;4s&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;        -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.inference (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;3s&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Traces&lt;/strong&gt; answer: “What path did this request take through my agents?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Logs&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Traditionally in software, logging provides an inside view into the behaviour and flow of the application.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;These provide a way to understand what happened throughout a particular request or session, and catch also critical information such as exceptions.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In OpenTelemetry, the logs also are captured with the respective traces so they can be connected respectively.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2024&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;45&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; INFO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [trace_id=abc123] Starting message processing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2024&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;47&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DEBUG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [trace_id=abc123] Model response: calling tool &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;web_search&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2024&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;53&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ERROR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [trace_id=abc123] Tool execution failed: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;API&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rate limited&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Logs&lt;/strong&gt; answer: “What did the agent ‘think’ at each step?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Metrics&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The metrics provide granular time-based KPIs that evolve over time, and can be aggregated and windowed to tell a particular historical story.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Store number of tokens per request&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Store success &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; failure rate of requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Store latency &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model calls&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Metrics&lt;/strong&gt; answer: “How is my system performing overall?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Bringing it all together&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The magic happens when these three are correlated (aka connected).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This allows us to do things like “click on that ERROR log in your observability backend” and diagnose the exact span in the trace where the failure occurred.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;multi-agent-context-propagation&quot;&gt;Multi-Agent Context Propagation&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The real challenge comes with multi-agent systems. When Agent A delegates to Agent B, which delegates to Agent C, you want a single unified trace - not three disconnected ones.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This requires &lt;strong&gt;context propagation&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This involves passing trace context through HTTP headers using the W3C Trace Context standard.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The result is a unified trace across all agents - here’s an example that shows how a trace context spans across the coordinator agent, the researcher agent and the analyst agent.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;coordinator.agent.agentic_loop (trace_id: abc123)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; coordinator.model.inference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; coordinator.delegate.researcher&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	    -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; researcher.agent.agentic_loop (trace_id: abc123)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	        -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; researcher.model.inference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	        -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; researcher.tool.web_search&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; coordinator.model.inference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; coordinator.delegate.analyst&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	    -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; analyst.agent.agentic_loop (trace_id: abc123)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	        -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; analyst.model.inference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;	        -&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; analyst.tool.calculator&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;Without context propagation, multi-agent debugging is just distributed guessing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;the-practical-use-case-a-multi-agent-research-system&quot;&gt;The Practical Use-Case: A Multi-Agent Research System&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s now start building something concrete.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We’ll use &lt;strong&gt;&lt;a href=&quot;https://github.com/axsaucedo/kaos?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;KAOS&lt;/a&gt;&lt;/strong&gt;&lt;a href=&quot;https://github.com/axsaucedo/kaos?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;(Kubernetes Agent Orchestration System)&lt;/a&gt;, an open-source framework to deploy, manage and scale multi-agent systems in Kubernetes.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;the-multi-agent-system-to-monitor&quot;&gt;The Multi-Agent System to Monitor&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Our use-case consists of a coordinator agent that delegates research and analysis tasks to specialist sub-agents:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-02.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 2: Simplified architecture of the multi-agent system to monitor&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Simplified architecture of the multi-agent system to monitor&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Each component—agents, tools, and model APIs—sends traces, metrics, and logs to an OpenTelemetry collector, which forwards everything to your chosen backend for visualization and analysis.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;prerequisites-commands--tools&quot;&gt;Prerequisites: Commands &amp;#x26; Tools&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Before we start, you’ll need:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;KAOS CLI&lt;/strong&gt; installed: &lt;code&gt;pip install kaos-cli==0.2.7&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;An LLM API key&lt;/strong&gt; (Any provider like OpenAI, Nebius, etc)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kubectl&lt;/strong&gt;, &lt;strong&gt;helm&lt;/strong&gt; and a &lt;strong&gt;Kubernetes cluster&lt;/strong&gt; (KIND, minikube, or a cloud cluster)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;installing-kaos&quot;&gt;Installing KAOS&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;First, let’s install the KAOS operator with OpenTelemetry enabled and an observability backend. We’ll use SigNoz as an open-source, OpenTelemetry-native option.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Using the KAOS CLI&lt;/strong&gt; (recommended):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Install the KAOS operator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; system&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --set&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; logLevel=DEBUG&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --wait&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --monitoring-enabled&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # Enables monitoring setup (supports signoz and jaeger)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Verify the installation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; system&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; status&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Change context to use (+create) this current namespace for convenience&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; system&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; working-namespace&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; kaos-hierarchy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once it’s running we can create our multi-agent system using one of the samples provided with the CLI.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can also see the ANNEX at the end of the blog post to deploy each of the components one by one.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; samples&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    3-hierarchical-agents&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --provider&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; openai&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --wait&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --api-secret&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # This will prompt your api-key secret&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can see the —provider flag which specifies the backend, such as nebius, gemini, bedrock and 100s of other providers &lt;a href=&quot;https://axsaucedo.github.io/kaos/v0.2.6/operator/modelapi-crd.html?ref=hackernoon.com#wildcard-mode-with-provider&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;[KAOS docs]&lt;/a&gt;, as well as your —api-secret which will be prompted interactively.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once installed you open the UI with the following command.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ui&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --monitoring-enabled&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;This allows us to see the deployed multi-agent system:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-03.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 3: KAOS Multi-Agent System - Hierarchical Sample&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;KAOS Multi-Agent System - Hierarchical Sample&lt;/p&gt;
&lt;hr data-reveal=&quot;&quot;&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;putting-it-all-together-monitoring-kaos&quot;&gt;Putting It All Together: Monitoring KAOS&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now let’s generate some traffic and start monitoring KAOS.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;interacting-with-agents&quot;&gt;Interacting with Agents&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can interact with agents in multiple ways:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Invoke the coordinator agent directly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;kaos agent invoke supervisor \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;  --&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Research the current AI chip market and calculate the market share of the top 3 companies.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Activating the Chat through the User Interface:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-04.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 4: Querying the Supervisor through the User Interface&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Querying the Supervisor through the User Interface&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Behind the scenes, this triggers a complex chain of operations:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;Supervisor receives the request&lt;/li&gt;
&lt;li&gt;Supervisor calls the LLM, which decides to delegate&lt;/li&gt;
&lt;li&gt;Researcher agent is invoked for market research (and calls two researcher sub-agents)&lt;/li&gt;
&lt;li&gt;Analyst agent calculates market shares (and calls two analyst sub-agents)&lt;/li&gt;
&lt;li&gt;Supervisor synthesizes the final response&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;All of this is caputred in auditable traces: every LLM call, every tool execution, every delegation.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;viewing-traces-understanding-request-flow&quot;&gt;Viewing Traces: Understanding Request Flow&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Why traces matter for agentic systems&lt;/strong&gt;: Unlike traditional request-response services, agents make multiple decisions per request. Traces let you see each decision point, how long it took, and what path the agent chose.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;The trace list shows all requests flowing through your agents. Each trace represents a complete user interaction.&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Click on a trace to see the full request flow:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-05.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 5: View the request traces and spans.&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;View the request traces and spans.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;A single trace showing the coordinator delegating to researcher and analyst agents, with each span representing a distinct operation.&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This trace visualization answers questions that would otherwise require hours of log spelunking:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Why did this request take 15 seconds?&lt;/strong&gt; The web_search tool took 8 seconds.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Which agents were involved?&lt;/strong&gt; Coordinator → Researcher → Analyst → Coordinator.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How many LLM calls were made?&lt;/strong&gt; 6 calls across the three agents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Did any tools fail?&lt;/strong&gt; All tools completed successfully (green spans).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;log-correlation-understanding-agent-reasoning&quot;&gt;Log Correlation: Understanding Agent Reasoning&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Traces tell you &lt;em&gt;what&lt;/em&gt; happened. Logs tell you &lt;em&gt;why&lt;/em&gt;. OpenTelemetry correlates them automatically through &lt;code&gt;trace_id&lt;/code&gt; and &lt;code&gt;span_id&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Every log entry includes these identifiers, enabling you to:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;Click on a span in your trace&lt;/li&gt;
&lt;li&gt;View all logs emitted during that span&lt;/li&gt;
&lt;li&gt;Understand the agent’s reasoning at each step&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;It is possible to see the view of the logs themselves as well as further details.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-06.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 6: Double click on specific trace to see correlated logs&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Double click on specific trace to see correlated logs&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We can then drill deeper into individual log entries.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Here for example we can view the log &lt;em&gt;“Delegation task: …”.&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This shows us the entire prompt that was delegated, which is quite useful for diagnostics and debugging.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-07.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 7: Clicking into a log for viewing the metadata and content&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Clicking into a log for viewing the metadata and content&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This includes &lt;em&gt;full log context including all attributes, resource labels, and the complete message.&lt;/em&gt;&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;exception-tracking-finding-production-issues&quot;&gt;Exception Tracking: Finding Production Issues&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;In production, things fail. OpenTelemetry captures exceptions as first-class citizens, and attaches them to the span where they occurred.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We can try this by asking the supervisor to delegate to a non-existing sub-agent:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Invoke the coordinator agent directly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;kaos agent invoke supervisor \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;  --&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;We are now testing valid exception functionality. Try to delegate to a non-existing agent to validate that it works correctly.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Or directly via the UI:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-08.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 8: Sending an incorrect delegation request to test the system.&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Sending an incorrect delegation request to test the system.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If we now navigate to the Exceptions tab, we can now see that there is an entry. This is the Exceptions list view, where all exceptions for the time period are listed.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This list captures errors across the system and correlates them also with the respective request traces, and logs.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We are also able to filter by different (agent) services, as well as other attributes.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-09.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 9: Showing the list of exceptions captured.&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Showing the list of exceptions captured.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We can see clearly that the exception was due to an attempted incorrect delegation.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;And we can also visualise the error in the trace view.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-10.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 10: Trace view for exceptions&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Trace view for exceptions&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;metrics-operational-overview&quot;&gt;Metrics: Operational Overview&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;While traces show individual requests, metrics show trends over time.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Here are some example key metrics in agentic systems:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;




























&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Metric&lt;/th&gt;&lt;th&gt;What It Tells You&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;kaos.requests&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Request volume by agent&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;kaos.request.duration&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Latency distribution (P50, P95, P99)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;kaos.model.calls&lt;/code&gt;&lt;/td&gt;&lt;td&gt;LLM API usage (cost indicator)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;kaos.tool.calls&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Tool execution frequency&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;kaos.delegations&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Multi-agent coordination patterns&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;These metrics enable alerting on production issues:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Request latency &gt; 30s&lt;/li&gt;
&lt;li&gt;Error rate &gt; 5%&lt;/li&gt;
&lt;li&gt;Model call failures &gt; 1%&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;We can also visualise them:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-11.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 11: Metrics dashboard showing request rates, latency percentiles, error rates, and token usage across all agents.&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Metrics dashboard showing request rates, latency percentiles, error rates, and token usage across all agents.&lt;/p&gt;
&lt;hr data-reveal=&quot;&quot;&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;under-the-hood-how-it-works&quot;&gt;Under the Hood: How It Works&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that you’ve seen observability in action, let’s dive into how it’s implemented. The challenges here aren’t obvious until you start building—and the solutions are broadly applicable to any agentic system.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;the-architecture&quot;&gt;The Architecture&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;KAOS separates control plane (Go) from data plane (Python); inside the Python application we have a OpenTelemetry manager (KaosOtelManager) to provide utilities to simplify the workflows.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-12.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 12: KAOS architecture&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;KAOS architecture&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;The key insight: &lt;strong&gt;telemetry configuration flows from Operator -&gt; Data Plane -&gt; OTEL Collector&lt;/strong&gt;. Users configure telemetry once in &lt;code&gt;values.yaml&lt;/code&gt;, and the operator propagates it to all components.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;instrumenting-the-core-logic&quot;&gt;Instrumenting the Core Logic&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;When it comes to agentic systems, it is not just about instrumenting the request-response, but it’s also about capturing the flow across the agent iterations.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;To start with we ensure that we capture the overarching span across the top level request/response. We then should also instrument other key components such as the Agentic Loop (example below), as well as extra calls such as MCP calls, and agent delegations.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# This is the same function pseudo-code that we showed initially but instrumented&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; process_message&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, session_id: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, messages: List[Dict]) -&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;&quot;&quot;Process message through agentic loop with full tracing.&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Start root span for entire message processing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    span &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; otel.span_begin(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;agent.agentic_loop&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, SpanKind.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;INTERNAL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    span.set_attribute(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;agent.name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    span.set_attribute(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;session.id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, session_id)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    span.set_attribute(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;agent.max_steps&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.max_steps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    span_failure &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; False&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # Agentic loop logic (see below)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    except&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Exception&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; e:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # If exception mark as failure&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        span_failure &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; True&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        otel.span_failure(span, e)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        raise&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    finally&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; not&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; span_failure:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            otel.span_success(span, e)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;instrumenting-the-agentic-loop&quot;&gt;Instrumenting the Agentic Loop&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We can now use the same pattern in the agentic loop, where we can capture the iterations with the respective context. This will be important as we can also capture the correlated logs and metrics that are connected to this particular request.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Previous logic outlined above...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; step &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.max_steps):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;            # Span for each iteration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            step_span &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; otel.span_begin(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;agent.step.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;step &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            step_span.set_attribute(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;step&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, step &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            agent_span_failed &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; False&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;                # MCP Calls (with OTEL span)...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;                # Delegation Calls (with OTEL span)...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            except&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Exception&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; e:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                otel.span_failure(step_span, e)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                agent_span_failed &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; True&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                raise&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            finally&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; not&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; agent_span_failed:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                    otel.span_success(span)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Preview logic outlined above...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Having the spans defined in placed is what allows us to trace the request across hops.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Some useful patterns to note:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Hierarchical spans&lt;/strong&gt;: There is a parent span for the loop, child spans for each step, grandchild spans for operations, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Log before span close&lt;/strong&gt;: Logs are emitted while trace context is active, which allows correlating the logs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explicit span management&lt;/strong&gt;: We are using explicit try/finally pattern to ensure spans are always closed, but we can also use context managers (i.e. &lt;code&gt;with&lt;/code&gt; clause)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is also what allows us to then visualise the breakdown of the request traces and spans.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-13.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 13: Zoomed-in the traces captured.&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;Zoomed-in the traces captured.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;context-propagation-for-multi-agent-systems&quot;&gt;Context Propagation for Multi-Agent Systems&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;When delegating to sub-agents (running in separate pods), we must propagate trace context:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Inject context into outgoing request&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opentelemetry.propagate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inject&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; delegate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, target_agent: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, task: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) -&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    headers &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Inject current trace context into headers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    inject(headers)  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Adds &apos;traceparent&apos; and &apos;tracestate&apos; headers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; httpx.AsyncClient() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; client:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        response &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; client.post(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;target_agent&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/v1/chat/completions&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;            headers&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;headers,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;            json&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;messages&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: task}]}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.json()[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;choices&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;ensuring-trace-context-propagates&quot;&gt;Ensuring Trace Context Propagates&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We also need to make sure that the context is received and embedded.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Extract context from incoming request&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opentelemetry.propagate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; extract&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@app.post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;/v1/chat/completions&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; chat&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(request: Request, body: ChatRequest):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Extract trace context from incoming headers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    context &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; extract(request.headers)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Attach to current context so new spans are children&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    token &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; otel_context.attach(context)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; agent.process_message(body.messages)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    finally&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        otel_context.detach(token)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;log-export-and-correlation&quot;&gt;Log Export and Correlation&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;For log-trace correlation, we connect Python’s logging to OpenTelemetry.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you have used previously something like the ELK stack, with OpenTelemetry now you have a setup where the logs are pushed as opposed to pulled, using the GRPC OTEL connection.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The logging instrumentation automatically injects &lt;code&gt;trace_id&lt;/code&gt; and &lt;code&gt;span_id&lt;/code&gt; into log records when there’s an active span context.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;To set up this connection, you can configure it with a few lines as outlined below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opentelemetry.sdk._logs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LoggerProvider&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opentelemetry.sdk._logs.export &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; BatchLogRecordProcessor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opentelemetry.exporter.otlp.proto.grpc._log_exporter &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; OTLPLogExporter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opentelemetry.instrumentation.logging &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LoggingInstrumentor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Set up OTLP log export&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;logger_provider &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LoggerProvider(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;resource)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;logger_provider.add_log_record_processor(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    BatchLogRecordProcessor(OTLPLogExporter(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;endpoint&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;endpoint))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Attach handler to Python root logger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;handler &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LoggingHandler(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;level&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;logging.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;logger_provider&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;logger_provider)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;logging.getLogger().addHandler(handler)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;metrics-for-agent-operations&quot;&gt;Metrics for Agent Operations&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We are also able to track metrics using the OpenTelemetry SDK.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you have used Prometheus in the past, the metrics in this case are not exposed through an endpoint that would be queried through a prometheus collector. Instead this also enables a push architecture where it’s sent to the OTEL collector through the GRPC OLTP connection to the OTel collector.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;When selecting metrics we aim to track metrics with low-cardinality labels to avoid cardinality explosions, as outlined in the sample below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opentelemetry &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; metrics&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;meter &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; metrics.get_meter(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;kaos-agent&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Counters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;request_counter &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; meter.create_counter(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;kaos.requests&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    description&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Number of requests processed&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    unit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model_call_counter &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; meter.create_counter(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;kaos.model.calls&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    description&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Number of model inference calls&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    unit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Histograms for latency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;request_duration &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; meter.create_histogram(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;kaos.request.duration&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    description&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Request processing duration in milliseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    unit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ms&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Usage example&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;request_counter.add(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;agent.name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.name, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;request_duration.record(duration_ms, {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;agent.name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.name})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Avoid high-cardinality labels&lt;/strong&gt;: Never use session IDs, user IDs, prompt content, or other unbounded values as metric labels. Put those in logs or trace attributes instead.&lt;/p&gt;
&lt;hr data-reveal=&quot;&quot;&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;the-tip-of-the-iceberg&quot;&gt;The Tip of The Iceberg&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is a gentle introduction to observability in multi-agent systems, and provides a high level view of what are some of the main components involved.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This should also provide you with enough intuition to instrument your agentic systems conscientiously, however you will need to identify which patterns work best in your particular contexts.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Instrumenting agentic AI systems with OpenTelemetry requires understanding the unique challenges these systems present:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Iterative loops&lt;/strong&gt; need span hierarchies that map to logical operations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-agent delegation&lt;/strong&gt; requires explicit context propagation using W3C Trace Context&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool execution&lt;/strong&gt; benefits from dedicated spans with clear naming&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Log-trace correlation&lt;/strong&gt; requires emitting logs before span close&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metrics&lt;/strong&gt; need low-cardinality labels to avoid storage explosions&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;The patterns we’ve covered apply to any agentic system, not just KAOS. Start instrumenting now.&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;The agents of tomorrow will be as ubiquitous as microservices are today, and OpenTelemetry gives you the visibility to operate them with confidence.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-reveal=&quot;&quot;&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;KAOS Framework&lt;/strong&gt;: &lt;a href=&quot;https://github.com/axsaucedo/kaos?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;github.com/axsaucedo/kaos&lt;/a&gt; - The open-source framework used in this article&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;KAOS Documentation&lt;/strong&gt;: &lt;a href=&quot;https://axsaucedo.github.io/kaos?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;axsaucedo.github.io/kaos&lt;/a&gt; - Full CLI and CRD documentation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenTelemetry Python&lt;/strong&gt;: &lt;a href=&quot;https://opentelemetry.io/docs/languages/python/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;opentelemetry.io/docs/languages/python&lt;/a&gt; - Official Python SDK documentation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenTelemetry GenAI Conventions&lt;/strong&gt;: &lt;a href=&quot;https://github.com/open-telemetry/semantic-conventions?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;github.com/open-telemetry/semantic-conventions&lt;/a&gt; - Emerging standards for AI observability&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SigNoz&lt;/strong&gt;: &lt;a href=&quot;https://signoz.io/?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;signoz.io&lt;/a&gt; - Open-source APM with native OpenTelemetry support&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;annex-creating-the-multi-agent-system-manually&quot;&gt;ANNEX: Creating the Multi-Agent System Manually&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this section we create the agentic system components manually instead of using the utilities for the curious ones!&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We’ll show you how you can do this with CLI but you can do this also with the UI as well as with &lt;code&gt;kubectl&lt;/code&gt; directly.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;step-1-we-first-connect-to-llms-with-a-modelapi&quot;&gt;Step 1: We first connect to LLMs with a ModelAPI&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The &lt;strong&gt;ModelAPI&lt;/strong&gt; resource in KAOS provides a unified interface for LLM access. It supports two modes:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Proxy Mode&lt;/strong&gt;: Routes requests through LiteLLM to external providers (OpenAI, Anthropic, Nebius, etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hosted Mode&lt;/strong&gt;: Pulls models into your cluster (via side-car) and runs it on the server for inference&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;The ModelAPI can be deployed easily via CLI.&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;Note that in order for our agents to use the model APIs we need to provide our authentication API Key. For this example we will be using &lt;a href=&quot;https://nebius.com/services/token-factory?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Nebius&lt;/a&gt; as it’s easy to set up, but you can also set up OpenAI, Gemini and dozen others.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; modelapi&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; llm-proxy&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --namespace&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; kaos-hierarchy&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --provider&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; nebius&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --api-key&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # When provided without value this prompts the key securely&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;From an observability perspective, the ModelAPI gives us visibility into model call latency, token usage, and error rates—critical metrics for understanding agent performance and controlling costs.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;step-2-deploy-the-mcp-tool-servers&quot;&gt;Step 2: Deploy the MCP Tool Servers&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;MCP (Model Context Protocol) Servers&lt;/strong&gt; in KAOS provide tools that agents can use.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;KAOS enables FastMCP native servers with ability to create and deploy your own images.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;KAOS also supports multiple native MCP runtimes via a registry. The most commonly used are:&lt;/p&gt;
&lt;div class=&quot;article-table-scroll&quot; tabindex=&quot;0&quot;&gt;
























&lt;table data-reveal=&quot;&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Runtime&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;python-string&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Define tools as inline Python functions for testing&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;kubernetes&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Kubernetes CRUD operations&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;slack&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Slack messaging integration&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;custom&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Your own container image&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p data-reveal=&quot;&quot;&gt;For our demo, we’ll create a calculator server. In production, you’d connect to real APIs, databases, or external services.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Note: In this section we use the &lt;code&gt;python-string runtime&lt;/code&gt; for quick testing, however for production-ready deployment use the &lt;a href=&quot;https://axsaucedo.github.io/kaos/v0.2.3/examples/custom-mcp-server.html?ref=hackernoon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;custom-image deployment&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;First we create the &lt;code&gt;calculator&lt;/code&gt; mcp, which will have a simple &lt;code&gt;add&lt;/code&gt; tool that will add two numbers and return the result.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ADD_TOOL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;def add(a: float, b: float) -&gt; float:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;&quot;&quot;Add two numbers together.&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    return a + b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; calculator&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --runtime&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; python-string&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --params&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; $ADD_TOOL &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --wait&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;And we then create an &lt;code&gt;echo&lt;/code&gt;mcp, which is also a simple tool that receives a string and returns the same value as the string.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ECHO_TOOL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;def echo(message: str) -&gt; str:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;&quot;&quot;Echo back the message for testing.&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    return f&quot;Echo: {message}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; echo-search&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --runtime&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; python-string&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --params&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; $ECHO_TOOL &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --wait&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;And we can send a request to test the mcp.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Run 2 + 2 on mcp calculator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; invoke&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; calculator&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;	--tool&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;	-a&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;	-a&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Run echo hello on mcp echo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; invoke&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; echo-search&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;	--tool&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;	-a&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Hello&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;From an observability standpoint we will show how it is important to understand the calls that are sent by any agent (or any external service) and processed by the MCP servers themselves&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3a-the-researcher-agent&quot;&gt;3a. The Researcher Agent&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The &lt;strong&gt;Agent&lt;/strong&gt; resource in KAOS represents an AI entity that can process requests, call models, execute tools, and delegate to other agents. Each agent:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Exposes an OpenAI-compatible &lt;code&gt;/v1/chat/completions&lt;/code&gt; endpoint&lt;/li&gt;
&lt;li&gt;Implements the agentic loop (model &gt; tools &gt; model &gt; …)&lt;/li&gt;
&lt;li&gt;Supports configurable memory for session state&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;The Researcher agent will specialise in gathering information:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; researcher&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --model&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;openai/gpt-4o&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; echo-search&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --description&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Research specialist&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --instructions&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;You research topics and provide .&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --expose=true&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --wait&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;For single-agent observability, we care about:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Model call latency&lt;/strong&gt;: How long does inference take?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool execution time&lt;/strong&gt;: Are tools responding quickly?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Step count&lt;/strong&gt;: How many iterations does the agent need?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3b-the-analyst-agent&quot;&gt;3b. The Analyst Agent&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The Analyst agent focuses on data analysis and calculations:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; analyst&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --model&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;openai/gpt-4o&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; calculator&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --description&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Data analyst with calculation capabilities&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --instructions&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;You analyze data and perform calculations.&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --expose=true&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --wait&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3c-the-supervisor-agent&quot;&gt;3c. The Supervisor Agent&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally, the Coordinator orchestrates the other agents. For multi-agent observability, we gain additional concerns:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Delegation patterns&lt;/strong&gt;: Which agents are called and how often?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-agent latency&lt;/strong&gt;: How much time is spent in delegation vs. local processing?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trace correlation&lt;/strong&gt;: Can we see the full request flow across agents?&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kaos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; subervisor&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --model&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;openai/gpt-4o&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --description&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Coordinator that delegates to specialist agents&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --instructions&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;You are a coordinator. Analyze user requests and delegate to your analyst and researcher.&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --sub-agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; researcher&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --sub-agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; analyst&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    --wait&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;And we’re done!&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can now go back to the top and run through the observability walkthrough with your deployed setup!&lt;/p&gt;&lt;/section&gt;</content:encoded><category>agents</category><category>observability</category><category>opentelemetry</category><category>kubernetes</category></item><item><title>Claude Code: It&apos;s not replacing devs. It&apos;s moving them to a higher altitude.</title><link>https://ethical.institute/blog/claude-code-higher-altitude/</link><guid isPermaLink="true">https://ethical.institute/blog/claude-code-higher-altitude/</guid><description>An exploration of the paradigms introduced by agentic development tools, lessons from building with AI tooling, and what they could mean for software engineering.</description><pubDate>Mon, 26 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;Join me in this post as I explore new paradigms brought by agentic development tools, lessons learned from building systems with AI tooling, and what that could mean for the software engineering practice (not “just coding”) within the next few years.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;“AI is making developers 10x” [&lt;/em&gt;&lt;a href=&quot;https://github.blog/news-insights/research/research-quantifying-github-copilots-impact-on-developer-productivity-and-happiness/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;em&gt;link&lt;/em&gt;&lt;/a&gt;&lt;em&gt;],&lt;/em&gt; &lt;em&gt;“AI is making developers less productive” [&lt;/em&gt;&lt;a href=&quot;https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;em&gt;link&lt;/em&gt;&lt;/a&gt;&lt;em&gt;],&lt;/em&gt; &lt;em&gt;“AI is coming for our jobs” [&lt;/em&gt;&lt;a href=&quot;https://www.windowscentral.com/artificial-intelligence/engineers-dont-write-code-anymore-anthropic-ceo-says-ai-is-about-to-eat-the-entire-profession&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;em&gt;link&lt;/em&gt;&lt;/a&gt;&lt;em&gt;], “AI enables coders” [&lt;/em&gt;&lt;a href=&quot;https://www.atlassian.com/blog/artificial-intelligence/how-ai-turns-software-engineers-into-product-engineers&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;em&gt;link&lt;/em&gt;&lt;/a&gt;&lt;em&gt;].&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Well, which one is it?&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s start this exploration with this meme:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;I’ve been thinking about this meme for a while. The punchline is feels like a great take to the question on how agentic development is impacting the software engineering practice.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;I’ve been able to further process this thought particularly as throughout the winter break I got a Copilot Pro subscription and went on a building spree; initially building one project per day, but then getting stuck on a longer project which provided me with a more clear view of what the future may look like for the tech industry.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;building-a-team-sized-projects-in-days-instead-of-weeks&quot;&gt;Building a team-sized projects in days instead of weeks&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;If someone was to tell me they single-handedly built a project that spans across custom Kubernetes operators, backend, frontend and SDKs, with robust CI &amp;#x26; release process within a couple of days, I would have struggled to believe them.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;That is about how shocked I was when I took on the challenge, and successfully built &lt;a href=&quot;https://github.com/axsaucedo/kaos&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;K.A.O.S.&lt;/strong&gt;&lt;/a&gt;in just a couple of days**, a Kubernetes Agent Orchestration System** that deploys and manges multi-agent systems, which consists of a non-trivial set of components:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Golang control-plane that manages the kubernetes native resources&lt;/li&gt;
&lt;li&gt;Python data-plane that implements Agents, MCPs and ModelAPI client/servers&lt;/li&gt;
&lt;li&gt;React based user interface with interactive CRUD, Agent chat, MCP debugging, etc&lt;/li&gt;
&lt;li&gt;CLI for managing resources and easily performing workflows&lt;/li&gt;
&lt;li&gt;CI/CD with KIND based e2e testing and automated release management&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Traditionally building a project like KAOS would’ve taken weeks, and would’ve required a handful of skilled individuals with different skill-sets (eg frontend, backend, infra, etc).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;But oh how things have changed.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;I was blazing through development milestones and the code was produced at real time speed. It got to the point where iteration cycles were faster than my capability to review changes and design further extensions. This brought two particular themes that really surprised me.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;surprise-1-time-constant--watching-tech-debt-form-in-real-time&quot;&gt;Surprise #1: Time Constant — Watching tech debt form in real time&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The first surprise was the &lt;strong&gt;time constant&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We all know tech debt is a real problem; in practice it creeps in slowly &amp;#x26; silently, and we only realise it when it’s too late. &lt;a href=&quot;https://martinfowler.com/bliki/TechnicalDebt.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;The interest payments eventually show up&lt;/a&gt;: small changes require larger investments, developer productivity stalls, interesting new bugs arise from everywhere, code areas become fragile, etc.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;What I was particularly surprised about was not about tech debt itself, but about &lt;strong&gt;the time constant&lt;/strong&gt; in which was being created**.** If at some point I came across an implementation that was slightly off (eg. a quick interface hack, a decision in the wrong layer, etc) and didn’t address it right there and then, within hours I could feel the codebase start bending around it.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;I have to say it was fascinating seeing tech debt form in a few hours in real time, when normally this spans across weeks, or even months.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This also coupled with the realisation that now I had the luxury to backtrack on particular implementation directions when seeing something was off. This was only possible due to low cost/effort for development.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This enabled for an &lt;strong&gt;exploration-exploitation branching-like&lt;/strong&gt;development approach, as opposed to a purely linear one where otherwise retracting may be too expensive compared to accepting the short term debt.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-01.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 2&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;surprise-2-cognitive-level--operating-at-a-higher-level-of-abstraction-whilst-staying-tactical&quot;&gt;Surprise #2: Cognitive Level — Operating at a higher level of abstraction whilst staying tactical&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The second surprise was at the &lt;strong&gt;cognitive level&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Historically when coding the traditional cycle is along the lines of: pick up a task, dive into a module, load that context into your brain’s RAM, and descend through levels of abstractions into the internals to fix what you can as further rabbit-holes arise (aka “being in the zone”). Basically this was the status quo, where we had accepted that our brains (+ typing speed) are the bottleneck.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;With agentic workflows, I noticed a different mode:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Load the entire picture at once and reason about at the &lt;strong&gt;system level&lt;/strong&gt;(backend, infrastructure, frontend, SDK, CI, etc) without losing the tactical thread.&lt;/li&gt;
&lt;li&gt;Delegate chunks of implementation whilst being able to steer the direction in real time whilst having the big picture in mind.&lt;/li&gt;
&lt;li&gt;Review the resulting artifacts as discrete, comprehensible deltas noting down extensions and improvements.&lt;/li&gt;
&lt;li&gt;Match against overarching direction otherwise backtrack and iterate; often with various threads in parallel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;This didn’t feel like I was “no longer coding”. It just felt like I was &lt;strong&gt;coding at a different altitude&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The way I like to think about this is the following analogy: how a tech lead or staff engineer thinks when they’re guiding the team(s) and shaping the system across months of development cycles, instead of just editing files.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-02.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 3&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;the-real-unlock-is-abstraction-specs-become-complex-systems&quot;&gt;The real unlock is abstraction: specs become complex systems&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now bringing these two “surprises” together is what makes me think: we have been over-emphasising the &lt;strong&gt;improved time constant&lt;/strong&gt; and under-discussing the &lt;strong&gt;higher cognitive level&lt;/strong&gt; that is being unlocked.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If we do now focus on the higher cognitive level unlocked, a more complex question arises:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;If we have unlocked this higher level of abstraction, what could this enable in practice?&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In organisations we may have a functional setups (teams of backend vs teams of frontend, etc) or cross functional setups (teams with mixes of frontend, backend, etc). Each of these team members would have a manager; teams of managers would report to a head of department; heads would report to a director; directors would report to… you get the point.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As of today, we build these layers because &lt;strong&gt;cognition&lt;/strong&gt; and &lt;strong&gt;coordination&lt;/strong&gt; don’t scale linearly. At some point, you need a layer whose job is &lt;strong&gt;not&lt;/strong&gt; writing the code, but &lt;strong&gt;steering&lt;/strong&gt; the system; i.e. aligning architecture, interfaces, guardrails, and operational quality. Further layers then arise to steer strategy, business priorities, etc — which may or may not be aligned with the execution (and vice-versa).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Why are we talking about organisational setups? Here is the twist: with this higher level of abstraction, a single developer may be able to move upwards to that next layer of cognitive abstraction &lt;em&gt;without giving up the ability to ship tactical changes&lt;/em&gt;. The metric is no longer “how fast do I code”; it becomes:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;How many layers of complexity can one person hold and steer effectively?&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;And once you look at it through that lens, the most interesting question becomes not “how many tickets can I close”, but:&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;what-is-an-example-of-what-we-could-build-at-this-higher-level-of-abstraction&quot;&gt;What is an example of what we could build at this higher level of abstraction?&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;The first potential answer to this question came up as I was exploring it through various conversations. Namely on the topic of a common organizational reality: departmental systems optimizing in silos.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In a typical e-commerce setup you might have separate systems for:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Pricing&lt;/strong&gt; — optimising discounting, demand shaping, stock clearance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replenishment&lt;/strong&gt; — optimising inventory coverage to enable re-stocking&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Marketing&lt;/strong&gt; — optimising campaigns, conversion, and demand spikes&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Each system can be locally &lt;em&gt;smart&lt;/em&gt;, but globally &lt;strong&gt;dumb&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Pricing may discount inventory down because it sees a stock issue. Replenishment may ramps stock up because it sees demand. Marketing may run a campaign that shifts demand curves. If these systems aren’t aligned, you get cannibalisation: adversarial optimisation that makes the overall customer lifetime value outcome worse.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Today, organizations try to solve this with process and coordination: roadmaps, planning, architecture governance, quarterly alignment, and a lot of “let’s align”. It works… sometimes. But it’s expensive and slow.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If individuals can operate one abstraction layer higher, it enforces that more of this coordination gets embodied in &lt;em&gt;systems&lt;/em&gt;, not meetings:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;shared constraints,&lt;/li&gt;
&lt;li&gt;shared feedback loops,&lt;/li&gt;
&lt;li&gt;shared intent,&lt;/li&gt;
&lt;li&gt;and shared operational reality.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-03.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 4&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;However, this still doesn’t answer my question; as it only provides the “means”, and not the “end”.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Namely it doesn’t answer the question: &lt;strong&gt;What is an &lt;em&gt;_actual&lt;/em&gt;_ example of what could be built at this level of abstraction?&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The next attempt was explored through the concept of programming languages:&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;from-objects-and-functions-to-architectural-primitives-k8s-crds-as-a-mental-model&quot;&gt;From objects and functions to architectural primitives (K8s CRDs as a mental model)&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;When thinking of this, the mental model I kept returning to was Kubernetes: specifically the &lt;a href=&quot;https://kubernetes.io/docs/concepts/extend-kubernetes/operator/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Operator Pattern — also known as Custom Resource Definitions (CRD)&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;A CRD is not just a schema. It’s a way to define a higher-level concept as architectural components that can be instantiated, reconciled, and operationalized into sophisticated and complex applications.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In the example of KAOS we abstract the concept of an &lt;a href=&quot;https://axsaucedo.github.io/kaos/v0.1.3/operator/overview.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Agent, or an MCP or a ModelAPI into an architectural component with a set of attributes&lt;/a&gt;, that reconciles into a broader set of system and application components that interact across a complex system.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;So the thought experiment then becomes:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;What if “programming language constructs” were CRD-level like architectural components; namely if we didn’t operate in objects but instead with dynamic architectural components via a &lt;em&gt;data plane&lt;/em&gt; of concepts which reconcile into services, policies, interactions, dependencies and so on.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is where another project I built (bit more half baked this one) gave me a different angle.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Basically, I wondered:&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;what-would-a-programming-language-look-like-if-it-natively-operated-at-the-next-level-of-abstraction&quot;&gt;What would a programming language look like if it natively operated at the next level of abstraction?&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;And before someone comes here to just shout “erlang!”, I want to explore a bit of blue sky thinking with a slightly more naive exploration. Starting with the idea of a programming language where an agent can be a first-class architectural component in a specification; then what happens if we design it where:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;modules are agents,&lt;/li&gt;
&lt;li&gt;control flow is agentic,&lt;/li&gt;
&lt;li&gt;and even the interpreter loop is an agent?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Not an interpreter in the classic sense (“parse -&gt; execute”), but something closer to a runtime that plans, delegates, reconciles, validates, and iterates.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;That line of thinking is what led me to experiment with &lt;a href=&quot;https://github.com/axsaucedo/agenticscript/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;AgenticScript&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; another weekend project — this time more half-baked — but that may help answer the bigger question.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;AgenticScript was an idea to a distributed agent programming language explicitly designed around coordination: agent spawning, inter-agent communication (ask / tell), tool management, a message bus, and rich debugging via a REPL that surfaces agent status, message bus performance, and communication flows.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It was really fun (and impressive) to work through a lexer, parser and interpreter with a code copilot (+ learned there’s a whole sub-field &lt;a href=&quot;https://en.wikipedia.org/wiki/Agent-oriented_programming&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;of Agent-Oriented Programming&lt;/a&gt;). However although it wasn’t a success in regards to pursuing the project end-to-end, it was a success in a different sense as it helped progress this question.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;And the answer seemed to lead to the potential of a more uncomfortable conclusion:&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;a-language-at-this-next-abstraction-layer-might-not-look-like-a-programming-language-at-all&quot;&gt;A language at this next abstraction layer might not look like a programming language at all&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;If we actually want a layer above today’s languages, it may not be a rigid syntax like we’re used to.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This line of thinking is closer to Andrej Karpathy’s famous 2023 phrase of &lt;a href=&quot;https://x.com/karpathy/status/1617979122625712128&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;“the hottest new programming language is English”&lt;/a&gt;. Not sure if it’s right to call this a “superset of human language”, but analogous to semi-structured Technical Design Documents (TDDs) that describe concepts, constraints, and components in ways that can compile into living artifacts that interact with broader systems.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Unsurprisingly, this is where the industry is already at the moment; large changes already require TDDs to be written before a solution is implemented.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The difference is that here “spec-driven development” would be framed as treating the specification as the source of truth and regenerating derived artifacts when it changes. And at the more radical end, there’s an explicit argument that code becomes a byproduct between requirements and system outcomes.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you zoom out, you can see this as the latest iteration of a long lineage of code generation that has been exploring “spec/models -&gt; generated artifacts” for years. The difference now is the “runtime” that would be required to execute such a new paradigm: the interpreter isn’t just executing instructions, &lt;strong&gt;it’s continuously reconciling intent against reality&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Which implies something important:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If we really want that future, the execution layer will likely be &lt;em&gt;more complex&lt;/em&gt; than most of the software we build today. Namely because it needs to absorb the semantic and operational burden that currently lives in teams, process, and organizational structure.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-04.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 5&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;a-pragmatic-cop-out-that-might-actually-be-the-answer&quot;&gt;A pragmatic cop-out (that might actually be the answer)&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;I can use this as a cop-out and say: maybe this already answers the question of what could be an example of what could be built at this higher level of abstraction.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;One plausible answer is:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;an ecosystem that itself exists at a higher abstraction layer (primitives, protocols, declarative intent),&lt;/li&gt;
&lt;li&gt;enabling individuals (and teams) to build at that same layer,&lt;/li&gt;
&lt;li&gt;with higher leverage in speed, integration, and reliability — iff the specs and guardrails are treated as first-class.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Which brings us right back to the meme.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-05.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 6&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;A “comprehensive and precise spec” is called code.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The shift is that we’re increasingly moving the definition of “code” upward: from functions and classes toward &lt;strong&gt;specifications, architectural primitives, and executable intent&lt;/strong&gt;.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;three-final-reflections-from-this-philosophical-rant&quot;&gt;Three final reflections from this philosophical rant&lt;/h2&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-were-heading-toward-an-agentic-sdlc-standardization-moment&quot;&gt;1) We’re heading toward an “agentic SDLC” standardization moment&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;I am getting flashbacks of the early 2010s, where many of us may remember those were the days where Scrum coaches were being hired everywhere to teach us “the way” of agile (and move away from the dark side of waterfall).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Whether or not you love Scrum, the pattern is the interesting part: &lt;strong&gt;practice standardizes after fragmentation&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;I expect something similar here:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;A small minority becomes visibly faster.&lt;/li&gt;
&lt;li&gt;Organizations try to replicate the gains.&lt;/li&gt;
&lt;li&gt;We get a proliferation of incompatible “agentic workflows.”&lt;/li&gt;
&lt;li&gt;Then we converge into a more standardized agentic SDLC — maybe even with something like “agentic coaches” (a phrase that sounds ridiculous until it doesn’t).&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;So it may not be too far until we start seeing agentic coaches as part of teams, pushing for day-long cycles, renaming spikes to something else (agentic runs?), and inventing another set of agentic poker cards (oh my).&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-developer-profiles-are-diverging-fast&quot;&gt;2) Developer profiles are diverging (fast)&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;And we’re already seeing the developer profiles shift. At least I have noticed three broad categories:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;High performers becoming disproportionately more productive.&lt;/li&gt;
&lt;li&gt;Low-discipline workflows becoming disproportionately more dangerous (generating code, not reading it, opening PRs before running it, creating more work downstream).&lt;/li&gt;
&lt;li&gt;The middle majority watching from the sidelines, waiting for “the way we do it here” to crystallize, instead of venturing into the unknown.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;This last group is important. Most industries don’t shift because early adopters are excited. They shift when norms, expectations, and playbooks form.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-the-bottleneck-moves-upstream-from-writing-code-to-judgment-constraints-and-verification&quot;&gt;3) The bottleneck moves upstream: from “writing code” to judgment, constraints, and verification&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The new 10x isn’t typing faster; it’s steering better. When you can generate and integrate &lt;em&gt;at&lt;/em&gt; a higher level, the differentiator becomes (a) what you choose to build, (b) how precisely you specify it, and © how aggressively you verify it.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is also where the tech debt surprise lands me: accelerated iteration doesn’t just accelerate output, it accelerates &lt;strong&gt;misalignment&lt;/strong&gt;. People have started naming the new type failure &lt;a href=&quot;https://failingfast.io/ai-epistemic-debt/?utm_source=chatgpt.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;em&gt;“epistemic debt”&lt;/em&gt;&lt;/a&gt;: shipping systems you can’t explain, defend, or reliably change (even if tests pass today).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;So the agentic SDLC endgame isn’t “everyone becomes 10x”. It is: &lt;strong&gt;speed becomes commoditised; rigour becomes the moat.&lt;/strong&gt; Teams that turn specs, guardrails, evals, and operational feedback loops into first-class artifacts get compounding leverage. Teams that don’t… compound confusion at machine speed.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It is now our responsibility as practitioners and leaders figure out this shift upwards in the cognitive stack; individuals can now do what teams could; teams can do what departments; and what follows should be able to invent the future. This analogy may go beyond the field of software engineering.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As they say: the future is here, it’s just not evenly distributed.&lt;/p&gt;&lt;/section&gt;</content:encoded><category>agents</category><category>claude-code</category><category>software-engineering</category></item><item><title>Beyond CUDA: GPU Accelerated Python for Machine Learning on Cross-Vendor Graphics Cards Made Simple</title><link>https://ethical.institute/blog/beyond-cuda-gpu-accelerated-python/</link><guid isPermaLink="true">https://ethical.institute/blog/beyond-cuda-gpu-accelerated-python/</guid><description>A practical deep dive into GPU Accelerated Python on cross-vendor graphics cards, building machine learning algorithms using the Kompute Python Framework and the Vulkan SDK.</description><pubDate>Fri, 13 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;Machine learning algorithms — together with many other advanced data processing paradigms — fit incredibly well to the parallel-architecture that GPU computing offers. This has driven massive growth in the advancement and adoption of graphics cards for accelerated computing in recent years. This has also driven exciting research around techniques that optimize towards concurrency, such as &lt;a href=&quot;https://mxnet.apache.org/versions/1.7/api/faq/model_parallel_lstm.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;model parallelism&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_parallelism&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;data parallelism&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this article you’ll learn how to write your own GPU accelerated algorithms in Python, which you will be able to run on virtually any GPU hardware — including non-NVIDIA GPUs. We’ll introduce core concepts and show how you can get started with the &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute#vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute Python framework&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;with&lt;/strong&gt;only a handful of lines of code.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-01.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 2&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Ben-Nun, Tal, and Torsten Hoefler. “Demystifying parallel and distributed deep learning: An in-depth concurrency analysis.” &lt;em&gt;ACM Computing Surveys (CSUR)&lt;/em&gt; 52.4 (2019): 1–43.&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;First we will be building a simple GPU Accelerated Python script that will multiply two arrays in parallel which this will introduce the fundamentals of GPU processing. We will then write a Logistic Regression algorithm from scratch on the GPU. Below are the core topics that we will cover, together with the respective resource links:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://pypi.org/project/kp/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute python package&lt;/a&gt; Installation&lt;/li&gt;
&lt;li&gt;GPU Accelerated &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/master/python/test/test_array_multiplication.py&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Array Multiplication Example&lt;/a&gt; in Python&lt;/li&gt;
&lt;li&gt;GPU Accelerated &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/master/python/test/test_logistic_regression.py&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Logistic Regression Example&lt;/a&gt; in Python&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;Only &lt;strong&gt;basic programming experience&lt;/strong&gt; is required for anyone reading this article, no knowledge of GPU computing is required. You can find the full code in the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;main repository&lt;/strong&gt;,&lt;/a&gt; and we also created an online Google Colab Notebook where you’ll be able to run the example with a GPU for free — you can find it in &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/master/examples/python&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;this link&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-02.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 3&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Google Colab Notebook with Examples for GPU&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;enter-kompute--the-vulkan-sdk&quot;&gt;Enter Kompute &amp;#x26; the Vulkan SDK&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;There are two parts to the Python framework we will be using today, both which are in the name itself —the &lt;strong&gt;Vulkan SDK&lt;/strong&gt;, and &lt;strong&gt;Kompute&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-03.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 4&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Playing “where’s waldo” with Khronos Membership (Image by Vincent Hindriksen via &lt;a href=&quot;https://streamhpc.com/blog/2017-05-04/what-is-khronos-as-of-today/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;StreamHPC&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The &lt;strong&gt;Vulkan&lt;/strong&gt;SDK is an Open Source project led by the &lt;a href=&quot;https://www.khronos.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Khronos Group&lt;/a&gt;, a consortium consisting of numerous tech companies that have come together to work towards defining and advancing the open standards for mobile and desktop media (and compute) technologies.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;A large number of high profile (and new) machine learning frameworks such as Google’s &lt;a href=&quot;https://github.com/tensorflow/tensorflow&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tensorflow&lt;/a&gt;, Facebook’s &lt;a href=&quot;https://github.com/pytorch/pytorch&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pytorch&lt;/a&gt;, Tencent’s &lt;a href=&quot;https://github.com/Tencent/ncnn&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NCNN&lt;/a&gt;, Alibaba’s &lt;a href=&quot;https://github.com/alibaba/MNN&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MNN&lt;/a&gt;—between others — have been adopting Vulkan as their core cross-vendor GPU computing SDK. This is primarily to enable the frameworks for cross platform and cross vendor graphics card support.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you can imagine, the Vulkan SDK provides very low-level C / C++ access to GPUs, which allows for very specialized optimizations. This is a great asset for GPU computing— the main disadvantage is the verbosity involved, requiring 500–2000+ lines of C++ code to only get the base boilerplate required to even start writing the application logic. This can result in expensive developer cycles and errors that can lead to larger problems. This was one of the main motivations for us to start the &lt;strong&gt;Kompute&lt;/strong&gt;project.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute#vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;The Kompute Python package&lt;/strong&gt;&lt;/a&gt; is built on top of the Vulkan SDK through optimized C++ bindings, which exposes Vulkan’s core computing capabilities. Kompute is the Python &lt;a href=&quot;https://en.wikipedia.org/wiki/General-purpose_computing_on_graphics_processing_units&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GPGPU framework&lt;/a&gt; that we will be using in this tutorial to build the GPU Accelerated machine learning algorithms.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-04.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 5&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Kompute &lt;a href=&quot;https://ethicalml.github.io/vulkan-kompute/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Documentation&lt;/a&gt; (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;installing-the-python-kompute-package&quot;&gt;Installing the Python Kompute Package&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order for us to start using the Kompute Python Package we will need to install its required dependencies. The package is available in Pypi, which means we can install it with &lt;code&gt;pip install&lt;/code&gt;. You will however require the following key components installed on your machine before being able to use it:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;CMAKE v3.41+ (install in &lt;a href=&quot;https://tulip.labri.fr/TulipDrupal/?q=node%2F1081&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Windows&lt;/a&gt;, &lt;a href=&quot;https://vitux.com/how-to-install-cmake-on-ubuntu-18-04/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Linux (Ubuntu)&lt;/a&gt;, &lt;a href=&quot;https://stackoverflow.com/a/59825656/1889253&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mac&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Vulkan SDK installed via &lt;a href=&quot;https://vulkan.lunarg.com/sdk/home&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;official website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;C++ compiler (eg. gcc for linux / mac, MSVC for Windows)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once you have these dependencies installed, you can simply run:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;pip install kp==0.5.1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;You should now see a success message confirming that the Kompute Python package has been installed. You can try it out yourself in the Google Colab Notebook &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/master/examples/python&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;provided in the repository&lt;/a&gt;, which you can set up with a GPU.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;writing-your-first-kompute-gpu-multiplication&quot;&gt;Writing your first Kompute: GPU Multiplication&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;To build our first simple array-multiplication GPU computing application using Kompute, we will write a simple python program that will do the following:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;Create a Kompute Manager (selects device 0 by default)&lt;/li&gt;
&lt;li&gt;Create Kompute Tensors to hold data (two input one output)&lt;/li&gt;
&lt;li&gt;Initialise the Kompute Tensors in the GPU&lt;/li&gt;
&lt;li&gt;Define the code to run on the GPU&lt;/li&gt;
&lt;li&gt;Dispatch GPU shader execution against Kompute Tensors&lt;/li&gt;
&lt;li&gt;Use Kompute Operation to map GPU output data into local Tensors&lt;/li&gt;
&lt;li&gt;Print your results&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;The full Python code required is quite minimal, so we are able to show the full script below. We’ll break down each of the sections in more detail.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pyshader &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 1. Create Kompute Manager (selects device 0 by default)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Manager()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 2. Create Kompute Tensors to hold data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_in_a &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_in_b &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 3. Initialise the Kompute Tensors in the GPU&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr.eval_tensor_create_def([tensor_in_a, tensor_in_b, tensor_out])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 4. Define the multiplication shader code to run on the GPU&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@ps.python2shader&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_shader_multiply&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(index&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;GlobalInvocationId&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.ivec3),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                            data1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                            data2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                            data3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32))):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; index.x &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Fetch the current run index being processed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    data3[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data1[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data2[i] &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Perform multiplication&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 5. Dispatch algorithm execution against Kompute Tensors&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr.eval_algo_data_def(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  [tensor_in_a, tensor_in_b, tensor_out],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  compute_shader_multiply.to_spirv())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 6. Sync tensor data from GPU back to local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr.eval_tensor_sync_local_def([tensor_out])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 7. Print results&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tensor_out.data()) &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# prints [2.0, 4.0, 6.0]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-create-a-kompute-manager-selects-device-0-by-default&quot;&gt;1. Create a Kompute Manager (selects device 0 by default)&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;First, we’ll create our Kompute Manager, which is in charge of creating and managing all the underlying Vulkan resources.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Manager()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you can see, here we are initializing our Kompute Manager, which by default creates all the base Vulkan resources on Device 0 (in my case it’s an NVIDIA card, and Device 1 is my integrated graphics card). For more advanced use-cases it’s also possible to provide the underlying GPU queues that you’d like to load — in &lt;a href=&quot;https://towardsdatascience.com/parallelizing-heavy-gpu-workloads-via-multi-queue-operations-50a38b15a1dc&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;this other tutorial&lt;/a&gt; we show how this can lead to significant speedups, but this is outside of scope of this article.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-create-kompute-tensors-to-hold-data-two-input-one-output&quot;&gt;2. Create Kompute Tensors to hold data (two input one output)&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will now create the Kompute Tensors that will be used for input and output. These will hold the data required which will be mapped into the GPU to perform this simple multiplication.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_in_a &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_in_b &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;When the tensors are created, the data is only initialized in the local CPU memory (aka RAM), but in order to use it in the GPU we’ll have to map the data into the GPU memory.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-initialise-the-kompute-tensors-in-the-gpu&quot;&gt;3. Initialise the Kompute Tensors in the GPU&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have our Tensors created with local data, we will map the data into the GPU. For this we will use the &lt;code&gt;eval_tensor_create_def&lt;/code&gt;, which will initialize the underlying Vulkan buffer and GPU memory, and perform the respective mapping into the GPU.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr.eval_tensor_create_def([tensor_in_a, tensor_in_b, tensor_out])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;4-define-the-code-to-run-on-the-gpu&quot;&gt;4. Define the code to run on the GPU&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we’ve initialized the necessary Kompute Tensor components and they are mapped in GPU memory, we can add the Kompute Algorithm that will be executed in the GPU. This is referred to as the “shader” code, which we build using the &lt;code&gt;pyshader&lt;/code&gt;library. You can see the full shader code below, and we’ll break down each of the section below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@ps.python2shader&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_shader_multiply&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(index&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;GlobalInvocationId&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.ivec3),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                            data1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                            data2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                            data3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32))):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; index.x &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Fetch the current run index being processed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    data3[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data1[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data2[i]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The GPU shader code can be defined as a Python function with the decorator &lt;code&gt;@ps.python2shader&lt;/code&gt; , and the parameters in this case include the variables that we’ll be using. This includes the Tensor inputs and outputs that we’ll be processing — the parameter format is the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;&amp;#x3C;param≥=(“&amp;#x3C;memory&gt;”, &amp;#x3C;binding&gt;, &amp;#x3C;type&gt;, ...)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case we are using Tensors with float values, which inherently would be equivalent to the &lt;code&gt;ps.Array&lt;/code&gt; value, with &lt;code&gt;ps.f32&lt;/code&gt; float values as elements.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The first parameter &lt;code&gt;index&lt;/code&gt; is of type &lt;code&gt;GlobalInvocationId&lt;/code&gt; , and provides the shader with the current index location in the execution GPU dispatch structure. This is what allows us to know what index in the parallel execution loop we are currently running, which is what we extract from the component &lt;code&gt;i = index.x&lt;/code&gt; — the reason why here we select &lt;code&gt;x&lt;/code&gt; is because the execution index can be defined as a &lt;code&gt;vec3&lt;/code&gt; component, where there would be execution indices for &lt;code&gt;inedx.x&lt;/code&gt; , &lt;code&gt;index.y&lt;/code&gt; and &lt;code&gt;index.z&lt;/code&gt; .&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The final component is the actual equation used, which in this case is a simple multiplication of the first and second parameter, and stored in the output (third) parameter.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;5-dispatch-gpu-shader-execution-against-kompute-tensors&quot;&gt;5. Dispatch GPU shader execution against Kompute Tensors&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order to run the shader above we will use the &lt;code&gt;eval_algo_data_def&lt;/code&gt;function. The parameters required for this Kompute Operation includes the Tensors to bind into the GPU instructions, as well as the GPU shader code that we defined in the Python function above.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr.eval_algo_data_def(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  [tensor_in_a, tensor_in_b, tensor_out],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  compute_shader_multiply.to_spirv())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;It’s worth mentioning that Kompute allows the user to also pass the shader as a raw glsl string, or alternatively a file path to a SPIR-V binary or raw glsl/hlsl file. For context, &lt;a href=&quot;https://www.khronos.org/opengl/wiki/SPIR-V&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SPIR-V is the intermediate representation&lt;/a&gt; that GPUs can use to process relevant operations.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;6-use-kompute-operation-to-map-gpu-output-data-into-local-tensors&quot;&gt;6. Use Kompute Operation to map GPU output data into local Tensors&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once the algorithm runs successfully, the result data will now be we held in the GPU memory of our output tensor. We can now use the function &lt;code&gt;eval_tensor_sync_local_def&lt;/code&gt; to sync the Tensor GPU memory into the local tensor.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr.eval_tensor_sync_local_def([tensor_out])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;7-print-your-results&quot;&gt;7. Print your results&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally, we can print the output data of our tensor.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tensor_out.data()) &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# prints [2.0, 4.0, 6.0]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;When you run this, you will see the values of your output tensor printed. That’s it, you’ve written your first Kompute!&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Although it may not seem obvious, the above introduced some intuition around core concepts and design thinking in GPU computing, whilst still abstracting a couple of the more in-depth concepts. In the following sections we will be providing more concrete terminology and at the end we’ll also outline a set of articles to dive into if you’re interested to learn more.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;diving-into-the-machine-learning-intuition&quot;&gt;Diving into the Machine Learning intuition&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we’ll look into the more advanced GPU compute use-case, specifically implementing the “hello world of machine learning”: &lt;strong&gt;logistic regression&lt;/strong&gt;. Before we cover the implementation we will provide some intuition on the concepts and the terminology that we’ll be using throughout the following sections.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In machine learning we always have two stages, training and inference. In the diagram below you can see the two simplified flows. At the top is the training flow, where you identify some data, extract some features, and train a model until you are happy with the accuracy. Once you have a trained model, you persist the model “weights” and deploy the model into the second workflow, where the model would perform inference on unseen data.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-05.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 6&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Data Science Process (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case we will have an input dataset &lt;code&gt;X&lt;/code&gt; , where each element is a pair &lt;code&gt;xi&lt;/code&gt; and &lt;code&gt;xj&lt;/code&gt; . Our input data will be the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;xi = { 0, 1, 1, 1, 1 }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xj = { 0, 0, 0, 1, 1 }&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;With this input data, the expected target value &lt;code&gt;Y&lt;/code&gt; to be predicted will be the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;Y = {0, 0, 0, 1, 1}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-06.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 7&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Logistic Regression Example from &lt;a href=&quot;https://www.datasciencecentral.com/profiles/blogs/why-logistic-regression-should-be-the-last-thing-you-learn-when-b&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;DS Central&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Our core objective in machine learning is to learn using this training data to find the function (and parameters) that will allow us to predict values &lt;code&gt;Y&lt;/code&gt; from new “previously unseen” inputs.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It’s worth noting that the predicted values will be defined as &lt;code&gt;ŷ&lt;/code&gt; , which are specifically the values computed with our “prediction” function, distinct to the “true” or “actual” values of &lt;code&gt;Y&lt;/code&gt; that we defined above.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The functions that we will be using for logistic regression will be the following:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-07.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 8&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s break down this function:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;z&lt;/code&gt; — is our linear mapping function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ŷ&lt;/code&gt; —is the resulting predicted outputs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X&lt;/code&gt;ᵀ —Transpose of the matrix of vectors we’ll represent as &lt;code&gt;x_i&lt;/code&gt; and &lt;code&gt;x_j&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;σ&lt;/code&gt; — The sigmoid function which is covered in more detail below&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;And the parameters that we’ll be looking to learn with our machine learning algorithm are:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;w&lt;/code&gt;— The weights that will be applied to the inputs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;b&lt;/code&gt; — The bias that will be added&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;There is also the surrounding function &lt;code&gt;σ&lt;/code&gt;which is the sigmoid function. This function forces our input to be closer to 0 or 1, which could be intuitively seen as the probability of our prediction to be “true” or “false”, and is defined as following:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-08.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 9&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is now the prediction/inference function that will allow us to process predictions from new data points. If we say for example that we have a new unseen set of inputs &lt;code&gt;X = { (0, 1) }&lt;/code&gt;, and we assume that the learned parameters were &lt;code&gt;W = (1, 1), b = 0&lt;/code&gt;after running our machine learning algorithm through our training data (which we’ll do later on), then we’ll be able to run this through our prediction function by substituting the values as follows:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-09.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 10&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case the prediction is &lt;code&gt;0.73...&lt;/code&gt;, which would be a positive prediction. This of course is just to demonstrate what our inference function will look like once we learn the parameters &lt;code&gt;W&lt;/code&gt; and &lt;code&gt;b.&lt;/code&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-10.gif&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 11&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Gradient descent visualized from &lt;a href=&quot;https://mi-academy.com/2018/10/04/the-history-of-gradient-descent/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ML Academy&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The way that we will be learning the parameters is by performing a prediction, calculating the error, and then re-adjusting the weights accordingly. The method used to “re-adjust” the weights based on the “prediction error” will be done by leveraging gradient descent. This will be repeated multiple times to find more accurate parameters.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For this we will need to use the derivatives of each of the formulas. The first one, which is the derivative of our linear mapping function &lt;code&gt;z&lt;/code&gt; is using the partial derivatives of the variables &lt;code&gt;w&lt;/code&gt;, &lt;code&gt;z&lt;/code&gt;and &lt;code&gt;b.&lt;/code&gt;First, the partial derivative &lt;code&gt;∂z&lt;/code&gt;:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;∂z = z(X) — y&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Where the variables are defined as follows:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;∂z&lt;/code&gt; — The partial derivative of the linear mapping function &lt;code&gt;z(x)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;z(X)&lt;/code&gt; — the result of the linear mapping function applied to input &lt;code&gt;x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;y&lt;/code&gt; — the actual value label expected for that input x&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Similarly the derivatives for w and b respectively are the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;∂w = (X — ∂z)/m&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;∂b = ∂z/m&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case &lt;code&gt;m&lt;/code&gt; is the total number of input elements.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will now be able to re-adjust the parameters using the above as follows:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;w = w — θ · ∂w&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;b = b — θ · ∂b&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case &lt;code&gt;θ&lt;/code&gt; is the learning rate, which as the name suggests controls the ratio by which the parameters will be modified on each iteration. Intuitively, the smaller, the more iterations it will be required for the algorithm to converge, however if the learning rate is too big, it will overshoot, leading to never being able to converge (from the image above you can imagine it will keep bouncing from side to side never reaching the bottom).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order for us to calculate loss, we will be using the log loss function, known also as cross-entropy loss function. This function is defined as follows:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-11.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 12&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Log loss (cross entropy loss) function&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-12.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 13&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Intuitive diagram to visualize cost function &lt;a href=&quot;https://machinelearningmastery.com/how-to-score-probability-predictions-in-python/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;from ML Mastery&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The function itself is set up such that the larger the difference between the predicted class and the expected class, the larger the error (you can see how much it punishes if the predicted class is on the complete different label).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The loss function will provide us an idea of the improvement of our algorithm across iterations.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally, one of the most important points here will be the intuition behind how we can leverage the parallel architecture of the GPU to optimize computation. In this case, we’ll be able to do it by processing multiple input parameters at the same time, referred to as a micro-batch, and then re-adjusting the parameters in batch. This is known as data-parallelization, and is one of many techniques available. In the next section we will see how this is implemented, namely passing a mini-batch of inputs, storing the weights, and then re-adjusting them before the next iteration.&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;Note: In this post we won’t delve into much detail, nor best practices on machine learning, however at the end of the article we will be listing a broad range of sources for people interested to take their machine learning (or GPU compute) knowledge to the next level.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have covered some of the core concepts, we will be able to learn about the implementation.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;machine-learning-gpu-shader-implementation&quot;&gt;Machine Learning GPU Shader Implementation&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;First we will start with the GPU compute shader, which is the code that will be executed in the GPU. The full shader is outlined below, and we’ll be breaking down each section in detail to explain what each part is doing.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@ps.python2shader&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_shader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        index   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;GlobalInvocationId&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.ivec3),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        x_i     &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        x_j     &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        y       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        w_in    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        w_out_i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        w_out_j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        b_in    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        b_out   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        l_out   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        M       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ps.Array(ps.f32))):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; index.x &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Fetch the current run index being processed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    m &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; M[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vec2(w_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], w_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    b_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    x_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vec2(x_i[i], x_j[i])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y[i]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    z_dot &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x_curr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; z_dot &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b_curr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y_hat &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; exp(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    d_z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_hat &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_curr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    d_w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; m) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_z&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    d_b &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; m) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_z&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    loss &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((y_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; log(y_hat)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_curr) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; log(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_hat)))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w_out_i[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_w.x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w_out_j[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_w.y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    b_out[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    l_out[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; loss&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-define-input-and-output-parameters&quot;&gt;1. Define input and output parameters&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;First we define all input parameters that are analogous to the input and output components we mentioned in the previous sections.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@python2shader&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_shader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        index   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;GlobalInvocationId&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ivec3),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        x_i     &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        x_j     &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        y       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        w_in    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        w_out_i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        w_out_j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        b_in    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        b_out   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        l_out   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        M       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32))):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you remember, at the end of the last section we mentioned how we will be leveraging the concept of micro-batches in order to use the parallel architecture of GPU processing. What this means in practice, is that we will be passing multiple instances of X to the GPU to process at a time, instead of expecting the GPU to process it one by one. This is why we see that above we have an array for &lt;code&gt;xi, xj, y, wOuti, wOutj,&lt;/code&gt;and&lt;code&gt;bOut&lt;/code&gt; respectively.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In more detail:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;The input &lt;code&gt;X&lt;/code&gt;as arrays &lt;code&gt;x_i&lt;/code&gt; and &lt;code&gt;x_j&lt;/code&gt; will hold the micro-batch of inputs&lt;/li&gt;
&lt;li&gt;The array &lt;code&gt;y&lt;/code&gt;will hold all the expected labels for micro-batch inputs&lt;/li&gt;
&lt;li&gt;The two input weight parameters &lt;code&gt;w_in_i&lt;/code&gt; and &lt;code&gt;w_out_j&lt;/code&gt; will be used for calculating predictions&lt;/li&gt;
&lt;li&gt;The input parameter &lt;code&gt;b&lt;/code&gt; which will be used for calculating the predictions&lt;/li&gt;
&lt;li&gt;The output weights &lt;code&gt;w_out_i&lt;/code&gt; and &lt;code&gt;w_out_j&lt;/code&gt;contains weights and will store the derivative of W for all micro-batches that should be subtracted&lt;/li&gt;
&lt;li&gt;Similarly the output bias array contains the derivatives of &lt;code&gt;b&lt;/code&gt;for all micro-batches that should be subtracted in batch&lt;/li&gt;
&lt;li&gt;Finally &lt;code&gt;l_out&lt;/code&gt; contains the output array where losses will be returned&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-define-the-size-of-the-input-buffers-as-m&quot;&gt;2. Define the size of the input buffers as M&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We also receive the constant &lt;code&gt;M&lt;/code&gt;, which will be the total number of elements — if you remember this parameter will be used for the calculation of the derivatives. We will also see how these parameters are actually passed into the shader from the Python Kompute side.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        M       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Array(f32))):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    m &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; M[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have all the input and output parameters defined, we can start defining the core logic, which will contain the implementation of our machine learning training algorithm.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-keep-track-of-the-execution-index&quot;&gt;3. Keep track of the execution index&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will need to keep track of the current index of the global invocation. Since the GPU executes in parallel, each of these runs will be running directly in parallel, so this allows the current execution to consistently keep track of what iteration index is currently being executed.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; index.x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;4-define-the-variables-from-the-input-parameters&quot;&gt;4. Define the variables from the input parameters&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We now can start preparing all the variables that we’ll be using throughout the algorithms. All our inputs are buffer arrays, so we’ll want to store them in &lt;code&gt;vec2&lt;/code&gt;and &lt;code&gt;float32&lt;/code&gt; variables.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vec2(w_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], w_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    b_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    x_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vec2(x_i[i], x_j[i])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y[i]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case we’re basically making explicit the variables that are being used for the current “thread run”. The GPU architecture consists of slightly more nuanced execution structures that involve thread blocks, memory access limitations, etc — however we won’t be covering these in this article.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we get into the more fun part — implementing the inference / predict logic. Below we will implement the inference logic to calculate &lt;code&gt;ŷ&lt;/code&gt;, which involves both the linear mapping function, as well as the sigmoid function which we defined above.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Inference and sigmoid logic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    z_dot &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x_curr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; z_dot &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b_curr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y_hat &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; exp(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;5-calculate-derivatives-to-re-adjust-parameters&quot;&gt;5. Calculate derivatives to “re-adjust” parameters&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have &lt;code&gt;y_hat&lt;/code&gt;, we can now use it to calculate the derivatives (&lt;code&gt;∂z&lt;/code&gt;, &lt;code&gt;∂w&lt;/code&gt; and &lt;code&gt;∂b&lt;/code&gt;), which in this case are the derivative of the currently-executed index input element.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    d_z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_hat &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_curr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    d_w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; m) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_z&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    d_b &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; m) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_z&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;6-calculate-the-loss-from-the-current-iteration&quot;&gt;6. Calculate the loss from the current iteration&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Using the expected prediction output and the calculated prediction output we are now able to compute the loss for the current iteration. As covered above, we are using the log loss (cross entropy) function to calculate the loss.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    loss &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((y_curr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; log(y_hat)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_curr) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; log(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_hat)))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;7-store-the-data-on-the-output-parameters&quot;&gt;7. Store the data on the output parameters&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally we are able to pass all respective calculated metrics to our output buffers. This will allow us to re-adjust for the next iteration.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w_out_i[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_w.x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w_out_j[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_w.y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    b_out[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; d_b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    l_out[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; loss&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We’ve now finished the shader that will enable us to train a Logistic Regression algorithm in the GPU —we will now cover the rest of the logic that will call this shader and orchestrate the machine learning training and inference. The full script is outlined below, and you can also try it in the Google Colab notebook with a GPU.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;machine-learning-orchestration-from-kompute&quot;&gt;Machine Learning Orchestration from Kompute&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will be using a few more advanced components from Kompute, which can be more intuitively visualised in the diagram below.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-13.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 14&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Kompute &lt;a href=&quot;https://ethicalml.github.io/vulkan-kompute/overview/reference.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Architecture Design&lt;/a&gt; (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;At the core of Kompute are Kompute “Sequences” and “Operations”, which are used for GPU actions. A Kompute Section can record and execute a batch of Kompute Operations for more efficient processing. In this example we will be leveraging Sequences to manage more efficient execution of the machine learning processing.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Similar to the example above, we will be will setting up the following steps:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;Create Kompute Manager with the device explicitly defined&lt;/li&gt;
&lt;li&gt;Create all the Kompute Tensors required&lt;/li&gt;
&lt;li&gt;Execute the Kompute Tensor GPU initialization via Kompute Manager&lt;/li&gt;
&lt;li&gt;Create Kompute Sequence and record operations for execution&lt;/li&gt;
&lt;li&gt;Iterate 100 times: Run micro-batch execution &amp;#x26; update weights&lt;/li&gt;
&lt;li&gt;Print resulting parameters to use for future inference&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you can see this is more involved than the simpler example we used above. In this case we will use the Kompute Sequence instead of the Kompute Manager directly, as we want to have deeper control on the commands that can be recorded to send in batch to the GPU. We will discuss this in more detail as we cover each of the steps. Let’s get started.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-create-kompute-manager-with-the-device-explicitly-defined&quot;&gt;1. Create Kompute Manager with the device explicitly defined&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will be creating the Kompute Manager with the device 0 explicitly defined — you can define another device as required.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Manager(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-create-all-the-kompute-tensors-required&quot;&gt;2. Create all the Kompute Tensors required&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we’ll be creating all the tensors required. In this sub-section you will notice that we will be referencing all the buffers/arrays that are being used in the shader. We’ll also cover how the order in the parameters passed relates to the way data is bound into the shaders so it’s accessible.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_x_i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_x_j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_w_in &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_w_out_i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_w_out_j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_b_in &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_b_out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_l_out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensor_m &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kp.Tensor([ tensor_y.size() ])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We also store them in a list &lt;code&gt;params&lt;/code&gt; for easier access:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;params &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [tensor_x_i, tensor_x_j, tensor_y, tensor_w_in, tensor_w_out_i,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    tensor_w_out_j, tensor_b_in, tensor_b_out, tensor_l_out, tensor_m]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-execute-the-kompute-tensor-gpu-initialization-via-kompute-manager&quot;&gt;3. Execute the Kompute Tensor GPU initialization via Kompute Manager&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The Kompute Tensor initialisation is quite standard so we’ll be able to do this step directly through the manager as we did in the simple array multiplication example previously.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mgr.eval_tensor_create_def(params)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ...latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;4-create-kompute-sequence-and-record-operations-for-execution&quot;&gt;4. Create Kompute Sequence and record operations for execution&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this section we will want to clear the previous recordings of the Kompute Sequence and begin recording a set of sequences. You will notice that unlike the previous section, in this case we won’t be running the &lt;code&gt;eval()&lt;/code&gt; straight away as we’ll have to first record the operations.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You will also notice that we will be recording three types of Kompute Operations through separate functions:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Clear previous operations and begin recording for new operations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sq.begin()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Record operation to sync memory from local to GPU memory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sq.record_tensor_sync_device([tensor_w_in, tensor_b_in])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Record operation to execute GPU shader against all our parameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sq.record_algo_data(params, compute_shader.to_spirv())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Record operation to sync memory from GPU to local memory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sq.record_tensor_sync_local([tensor_w_out_i, tensor_w_out_j, tensor_b_out, tensor_l_out])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Stop recording operations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sq.end()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;record_tensor_sync_device(...)&lt;/code&gt; — This operation ensures that the Tensors are synchronized with their GPU memory by mapping their local data into the GPU data. In this case, these Tensors use Device-only memory for processing efficiency, so the mapping is performed with a staging Tensor inside the operation (which is re-used throughout the operations for efficiency). Here we’re only wanting to sync the input weights, as these will be updated locally with the respective derivatives.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;record_algo_base_data(...)&lt;/code&gt; — This is the Kompute Operation that binds the shader that we wrote above with all the local CPU/host resources. This includes making available the Tensors. It’s worth mentioning that the index of the tensors provided as parameters is the order in which they are mapped in the shaders via their respective bindings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;record_tensor_sync_local(...)&lt;/code&gt;— This Kompute Operation performs a similar set of instructions as the sync operation above, but instead of copying the data to the GPU memory, it does the converse. This Kompute Operation maps the data in the GPU memory into the local Tensor vector so it’s accessible from the GPU/host. As you can see we’re only running this operation in the output tensors.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;5-iterate-100-times-run-micro-batch-execution--update-weights&quot;&gt;5. Iterate 100 times: Run micro-batch execution &amp;#x26; update weights&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have the command recorded, we can start running executions of these pre-loaded commands. In this case, we will be running the execution of a micro-batch iteration, followed by updating the parameters locally, so they are used in the following iteration.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Perform machine learning training and inference across all input X and Y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i_iter &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ITERATIONS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Execute an iteration of the algorithm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq.eval()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Calculate the parameters based on the respective derivatives calculated&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; j_iter &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tensor_b_out.size()):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tensor_w_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; learning_rate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensor_w_out_i.data()[j_iter]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tensor_w_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; learning_rate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensor_w_out_j.data()[j_iter]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tensor_b_in[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; learning_rate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensor_b_out.data()[j_iter]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;7-print-resulting-parameters-to-use-for-future-inference&quot;&gt;7. Print resulting parameters to use for future inference&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We now have a trained logistic regression model, or at least we’ve been able to optimize its respective function to identify suitable parameters. We are now able to print these parameters and use the parameters for inference in unseen datasets.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tensor_w_in.data()) &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# prints [0.00032, 1.58746]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tensor_b_in.data()) &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# prints [-0.794009]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;And we’re done!&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You are able to find this entire example in the example repository, which you’ll be able to run and extend.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;what-next&quot;&gt;What next?&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Congratulations, you’ve made it all the way to the end! Although there was a broad range of topics covered in this post, there is a massive amount of concepts that were skimmed through. These include the underlying Vulkan concepts, GPU computing fundamentals, machine learning best practices, and more advanced Kompute concepts. Luckily, there are a broad range of resources online to expand your knowledge on each of these. Some links I recommend as further reading include the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://kompute.cc/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Documentation&lt;/a&gt; for more details and further examples&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ethical.institute/mle.html&quot;&gt;The Machine Learning Engineer Newsletter&lt;/a&gt; if you want to keep updated on articles around Machine Learning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EthicalML/awesome-production-machine-learning/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Awesome Production Machine Learning&lt;/a&gt; list for open source tools to deploy, monitor, version and scale your machine learning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fast.ai/2018/09/26/ml-launch/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Introduction to ML for Coders course&lt;/a&gt; by FastAI to learn further machine learning concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-14.gif&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 15&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Image by Author&lt;/p&gt;&lt;/section&gt;</content:encoded><category>gpu</category><category>kompute</category><category>machine-learning</category><category>python</category></item><item><title>Parallelizing GPU-intensive Workloads via Multi-Queue Operations</title><link>https://ethical.institute/blog/parallelizing-gpu-workloads-multi-queue/</link><guid isPermaLink="true">https://ethical.institute/blog/parallelizing-gpu-workloads-multi-queue/</guid><description>Achieving 2x+ performance improvements on GPU-intensive workloads by leveraging multi-queue operation parallelism using Kompute and the Vulkan SDK.</description><pubDate>Sun, 18 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;GPUs have proven &lt;a href=&quot;https://arxiv.org/abs/1802.09941&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;extremely useful for highly parallelizable data processing use-cases&lt;/a&gt;. The computational paradigms found in machine learning &amp;#x26; deep learning for example fit extremely well to &lt;a href=&quot;http://cs149.stanford.edu/fall19/lecture/gpuarch/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the processing architecture graphics cards provide&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;However, when it comes to multiple GPU workloads, one would assume that these would be processed concurrently, but this is not the case. Whilst a single GPU compute workload is parallelized across the numerous GPU cores, multiple workloads are run one by one sequentially. That is of course &lt;strong&gt;until recent improvements in graphics card architectures&lt;/strong&gt;which are now enabling for hardware parallelization across multiple workloads. This can be achieved by submitting the workloads to different underlying physical GPU “queue families” that support concurrency. Practical tecniques in machine learning that would benefit from this include &lt;a href=&quot;https://mxnet.apache.org/versions/1.7/api/faq/model_parallel_lstm&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;model parallelism&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_parallelism&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;data parallelism&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this example we will show how we can achieve &lt;strong&gt;a 2x performance improvement&lt;/strong&gt; on a synchronous example by simply submitting multiple workloads across two queue families, resulting in these workloads running in parallel.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is an important optimization technique, as recent announcements outlined in NVIDIA’s Ampere GA10x architecture specifications &lt;a href=&quot;https://www.nvidia.com/content/dam/en-zz/Solutions/geforce/ampere/pdf/NVIDIA-ampere-GA102-GPU-Architecture-Whitepaper-V1.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;page 19 in this document&lt;/a&gt; will enable for &lt;strong&gt;3x performance improvements&lt;/strong&gt;(i.e. concurrency across one graphics queue and two compute queues)&lt;strong&gt;,&lt;/strong&gt; making it clear that this trend will only continue to bring further optimization improvements in this area.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will be implementing this using Vulkan and the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute framework&lt;/a&gt;. More specifically we will cover:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Disambiguation of “asynchronous” and “parallel” in GPU processing&lt;/li&gt;
&lt;li&gt;A base synchronous example that we will build upon&lt;/li&gt;
&lt;li&gt;Steps to extend the example for asynchronous workload submission&lt;/li&gt;
&lt;li&gt;Steps to extend the example for parallel multi-queue GPU processing&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can find the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/0b221c9ebd3c8d7c8a81ef2ce80627c9460ec9c2/test/TestAsyncOperations.cpp#L10&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;full code in this file&lt;/strong&gt;&lt;/a&gt; — instructions on how to run the full suite using CMAKE can be found in the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute#build-overview&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;main Kompute repository build section&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;about-vulkan-and-kompute&quot;&gt;About Vulkan and Kompute&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-01.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 2&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Khronos Membership (Image by Vincent Hindriksen via &lt;a href=&quot;https://streamhpc.com/blog/2017-05-04/what-is-khronos-as-of-today/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;StreamHPC&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Vulkan_(API)&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;The Vulkan SDK&lt;/strong&gt;&lt;/a&gt;is an Open Source project led by the &lt;a href=&quot;https://www.khronos.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Khronos Group&lt;/strong&gt;&lt;/a&gt;, which enables for highly optimized cross-vendor/cross-platform GPU processing.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute#vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute&lt;/strong&gt;&lt;/a&gt; is a framework built on top of the Vulkan SDK which abstracts the thousands of lines of boilerplate code required, introducing best practices that expose Vulkan’s core computing capabilities. Kompute is the &lt;a href=&quot;https://en.wikipedia.org/wiki/General-purpose_computing_on_graphics_processing_units&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GPGPU computing framework&lt;/a&gt; that we will be using in this tutorial to build the core asynchronous and parallel code implementation.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-02.gif&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 3&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;The “Komputer” from &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Repo&lt;/a&gt; (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;asynchronous-vs-parallel-processing&quot;&gt;Asynchronous vs Parallel Processing&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Before diving into the code, it is important to disambiguate two concepts — &lt;strong&gt;asynchronous workload submission&lt;/strong&gt; and &lt;strong&gt;parallel workload processing&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-03.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 4&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Simplified Vulkan Architecture (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The way parallel workloads are submitted for processing when using the &lt;strong&gt;Vulkan SDK&lt;/strong&gt;through &lt;strong&gt;GPU Queues&lt;/strong&gt;. This can be visualised in the simplified Vulkan Architecture diagram (pipeline and descriptor components were left out for simplicity).&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;asynchronous-workload-submission&quot;&gt;Asynchronous Workload Submission&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Asynchronous processing encompasses the ability for the CPU host side to be able to do other work whilst the GPU is processing the workload. “Other work” can include calling other C++ functions, or even submitting further workloads to the same or other GPU queues. When the CPU wants to check whether the GPU workload is finished, it can use a **Vulkan “Fence”**which is basically a semaphore resource that allows the CPU to be notified when a GPU workload finishes.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It is important to note that when multiple workloads are submitted to the same queue, even if these are done from multiple C++ threads, the expected execution ordering will still be sequential — at least as of today’s GPU architectures.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;parallel-workload-processing&quot;&gt;Parallel Workload Processing&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Parallel workload processing consists of the concurrent execution of two or more workloads by the GPU. More specifically, if you had two GPU tasks that would take 10 seconds each to process, the theoretical parallel execution would still take 10 seconds for both as they would be carried out at the same time.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order for parallel workload processing to be achieved, this is something that first and foremost has to be supported by the underlying GPU. The reason why this is important is because even if you were to submit workloads across different GPU queues, the processing may still be done sequentially by the underlying hardware based on its limitations.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;base-sequential-processing-example&quot;&gt;Base Sequential Processing Example&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will now take a look at the code that we will be using throughout this article. This first version of the code will be the sequential flow — we will be able to then convert it into asynchronous code, and finally into parallel code. We will basically be running a workload where we will be doing the following:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;Creating a Kompute Manager to orchestrate all GPU work&lt;/li&gt;
&lt;li&gt;Create Kompute Tensors in the CPU host that will be used to process data&lt;/li&gt;
&lt;li&gt;Map the Kompute Tensors into GPU Device memory&lt;/li&gt;
&lt;li&gt;Define compute shader which will keep the GPU busy for a few 100s ms&lt;/li&gt;
&lt;li&gt;Run compute shader in the GPU using the Tensors for data processing&lt;/li&gt;
&lt;li&gt;Map results of the Kompute Tensors back into CPU Host memory&lt;/li&gt;
&lt;li&gt;Verify that the operation was successful&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;For measuring time we will be using &lt;code&gt;&amp;#x3C;chrono&gt;&lt;/code&gt; from the standard library. We will be mainly using it to calculate the difference across a start and end time retrieved with &lt;code&gt;std::chrono::high_resolution_clock::now()&lt;/code&gt; as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; startSync &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;chrono&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;high_resolution_clock&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... code implementation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; end &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;chrono&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;high_resolution_clock&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; durationSync &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;chrono&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;duration_cast&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;chrono&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;microseconds&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        end &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; start).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;count&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can find the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/1053cde1f0d27799f0d7dbd8043919656498f8bf/test/TestAsyncOperations.cpp#L8&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;runnable code in this file&lt;/a&gt;, which is part of the Kompute test suite.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-creating-a-kompute-manager-to-orchestrate-all-gpu-work&quot;&gt;1. Creating a Kompute Manager to orchestrate all GPU work&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;First we have to create the Kompute Manager, which performs all the required memory management and creates all required Vulkan resources. By default the Kompute Manager will pick GPU Device 0, but you are able to pass the specific device index you would prefer to initialise with, and if preferred you can pass your Vulkan resources if you already have a Vulkan application.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Manager mgr;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // Selects device 0 and first compute queue unless explicitly requested&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-create-the-kompute-tensors-in-cpu-host-that-will-be-used-to-process-data&quot;&gt;2. Create the Kompute Tensors in CPU host that will be used to process data&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will now be able to create a set of Kompute Tensors. We first initialise the data in the CPU Host, consisting of an array of zeros with length of 10. We will be using two tensors as we’ll be running two algorithm executions. We will be able to check these Kompute Tensors at the end to confirm that the execution has been successful.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; zeros&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 1. Create a set of data tensors in host memory for processing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorA &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;make_shared&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(zeros));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorB &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;make_shared&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(zeros));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-map-the-kompute-tensors-into-gpu-device-memory&quot;&gt;3. Map the Kompute Tensors into GPU Device memory&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-04.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 5&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Stanford CS149 Course&lt;/strong&gt;&lt;a href=&quot;http://cs149.stanford.edu/fall19/lecture/gpuarch/slide_038&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;2019 Slides&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We are now able to copy the host data of the Kompute Tensors into the GPU Device memory.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpTensorCreate&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ tensorA, tensorB });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is an important step as by default the Kompute Tensors use device-only-visible memory which means that a GPU operation will need to copy it with a staging tensor.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Kompute allows us to create the buffer and GPU memory block, as well as performing a copy with a staging buffer through the &lt;code&gt;kp::OpTensorCreate&lt;/code&gt; operation.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;4-define-compute-shader-which-will-keep-the-gpu-busy-for-a-few-100s-ms&quot;&gt;4. Define compute shader which will keep the GPU busy for a few 100s ms&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The compute shader that we create has a relatively large loop to simulate an “expensive computation”. It basically performs a unit addition for &lt;code&gt;100000000&lt;/code&gt; iterations and adds the result to the input Tensor.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::string &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;shader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;R&quot;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        #version 450&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        layout (local_size_x = 1) in;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        layout(set = 0, binding = 0) buffer b { float pb[]; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        shared uint sharedTotal[1];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        void main() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            uint index = gl_GlobalInvocationID.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            sharedTotal[0] = 0;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            for (int i = 0; i &amp;#x3C; 100000000; i++)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                atomicAdd(sharedTotal[0], 1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            pb[index] = sharedTotal[0];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    )&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;5-run-compute-shader-in-the-gpu-using-the-tensors-for-data-processing&quot;&gt;5. Run compute shader in the GPU using the Tensors for data processing&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we are able to submit the compute shader for execution through the &lt;code&gt;kp::OpAlgoBase&lt;/code&gt; operation. This basically allows us to perform a submission of the shader with the respective tensor. This initial implementation runs the execution synchronously, so it will first run the execution of the shader with &lt;code&gt;tensorA&lt;/code&gt;, and then the execution of the same shader with &lt;code&gt;tensorB&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpAlgoBase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        { tensorA },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpAlgoBase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        { tensorB },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;6-map-results-of-the-kompute-tensors-back-into-cpu-host-memory&quot;&gt;6. Map results of the Kompute Tensors back into CPU Host memory&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally we want to retrieve the results from the GPU device memory into the CPU host memory so we can access it from C++. For this we can use the &lt;code&gt;kp::OpTensorSync&lt;/code&gt; operation.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpTensorSyncLocal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ tensorA, tensorB });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;7-verify-that-the-operation-was-successful&quot;&gt;7. Verify that the operation was successful&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally we can just check that both resulting &lt;code&gt;kp::Tensor&lt;/code&gt; contain the expected value of &lt;code&gt;100000000&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; expected&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100000000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    EXPECT_EQ&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(inputsSyncB[i]-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), expected);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;extending-for-asynchronous-workload-submission&quot;&gt;Extending for Asynchronous Workload Submission&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;The steps that we will need to extend for asynchronous submission in this case are quite minimal. The only thing we need to do is to substitute the &lt;code&gt;evalOpDefault&lt;/code&gt; function for the &lt;code&gt;evalOpAsyncDefault&lt;/code&gt; function, and then using the &lt;code&gt;evalOpAwaitDefault(&amp;#x3C;timeInNanoSecs&gt;)&lt;/code&gt; to wait until the job is finished. This basically would look as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpAsyncDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpAlgoBase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      { tensorB },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpAsyncDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpAlgoBase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      { tensorA },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;evalOpAwaitDefault&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you can see we are able to submit two tasks for processing asynchronously, and then wait until they are finished with the Await function.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It’s worth pointing out that every time we call &lt;code&gt;evalOpAsyncDefault&lt;/code&gt; it creates a new managed sequence, and &lt;code&gt;evalOpAwaitDefault&lt;/code&gt; only waits for the most recent default sequence. This means that in the snippet above, we are only waiting for the second asynchronous operation. This isn’t a problem for our example, but this could introduce bugs if we’re now aware. The proper way to do this is with explicitly created “named sequences” — we will do this in the next section.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;extending-for-parallel-workload-processing&quot;&gt;Extending for Parallel Workload Processing&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we know we are able to execute multiple workloads asynchronously, we are able to extend this to leverage the multiple queues in the GPU to achieve parallel execution of workloads.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;running-on-an-nvidia-1650-video-card&quot;&gt;Running on an NVIDIA 1650 Video Card&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order to show a useful example, we will dive into how this would be achieved in an &lt;a href=&quot;http://vulkan.gpuinfo.org/displayreport.php?id=9700&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NVIDIA 1650 video card&lt;/a&gt;. You are able to try this yourself by checking the device report of your video card — namely on the queue families and parallel processing capabilities available.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-05.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 6&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Conceptual Overview of Queues in NVIDIA 1650 (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The NVIDIA 1650 GPU has 3 queue families. Using &lt;code&gt;G&lt;/code&gt; for GRAPHICS, &lt;code&gt;T&lt;/code&gt; for TRANSFER and &lt;code&gt;C&lt;/code&gt; for COMPUTE capabilities, the NVIDIA 1650 has a &lt;code&gt;G+T+C&lt;/code&gt; family in &lt;code&gt;familyIndex 0&lt;/code&gt;with 16 queues, a &lt;code&gt;T&lt;/code&gt; family on &lt;code&gt;familyIndex 1&lt;/code&gt; with 2 queues, and a &lt;code&gt;T+C&lt;/code&gt; family on &lt;code&gt;familyIndex 2&lt;/code&gt; with 8 queues.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As of today (October 2020), NVIDIA does not support parallel processing of workloads when work is submitted across multiple queues within the same family. However it supports parallelizing when workloads are submitted across queue families. This means that workloads between graphics and compute family queues can be parallelized — we will be using this knowledge in our implementation.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;implementation-of-parallel-workflow-execution&quot;&gt;Implementation of Parallel Workflow Execution&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;So far we have been submitting all GPU workloads to a single queue, namely the GRAPHICS &lt;code&gt;familyIndex 0&lt;/code&gt; using the underlying queue index 0. In our case using the GPU 1650, we will be able to achieve parallel processing if we submit workloads across the GRAPHICS family and the COMPUTE family. The diagram below should provide an intuition on what we will be doing.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-06.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 7&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Operation Execution in Parallel through Multiple Family Queues (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order for us to do this, we will need to modify three key things:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;We initialise Kompute Manager with the respective queues available&lt;/li&gt;
&lt;li&gt;We create two Kompute Sequences with each respective queue allocated&lt;/li&gt;
&lt;li&gt;We run the operations on each respective queue&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will dive into each of these three points.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-we-initialise-kompute-manager-with-the-respective-queues-available&quot;&gt;1. We initialise Kompute Manager with the respective queues available&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;When initialising a manager we are able to pass an array containing the queues that we would like to fetch. In this case, we only fetch one graphics queue and one compute queue, however, based on the hardware specs of the NVIDIA 1650, we would be able to request up to 16 graphics queues (familyIndex 0), 2 transfer queues (familyIndex 1), and 8 compute queues (familyIndex 2).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    uint32_t&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; deviceId&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;uint32_t&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; queues&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Manager &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mgr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(deviceId, queues);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-we-create-two-kompute-sequences-with-each-respective-queue-allocated&quot;&gt;2. We create two Kompute Sequences with each respective queue allocated&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we are able to explicitly initialise two managed sequences, each allocated to a different queue, referencing the index of the array we passed in the previous step.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // The index is relative to the array we used to initialise&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createManagedSequence&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;graphicsQueueSequence&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createManagedSequence&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;computeQueueSequence&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-we-run-the-operations-on-each-respective-queue&quot;&gt;3. We run the operations on each respective queue&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we are able to run operations submitting to each respective queue. In this case both of the GPU workloads are submitted in parallel.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgrAsync.evalOpAsync&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpAlgoBase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      { tensorA },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;graphicsQueueSequence&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgrAsync.evalOpAsync&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpAlgoBase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      { tensorB },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;computeQueueSequence&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgrAsync.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;evalOpAwait&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;graphicsQueueSequence&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgrAsync.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;evalOpAwait&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;computeQueueSequence&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;parallel-workload-execution-results&quot;&gt;Parallel Workload Execution Results&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;When running the code provided above, we can see a 2x speed improvement in execution time thanks to the parallel family queue submission of workload. You can also see that if we were to submit to extra queues from the GRAPHICS or COMPUTE queues, we would not see any further speed improvements as intra-queue parallelization is not supported in this NVIDIA 1650 card.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can find the full code and run it in this file — instructions on how to run &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/0b221c9ebd3c8d7c8a81ef2ce80627c9460ec9c2/test/TestAsyncOperations.cpp#L10&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the full suite&lt;/a&gt; using CMAKE can be found in the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;main Kompute repository&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is a particularly important result, as based on the recent announcement from NVIDIA coming together with the release of their 300x video cards, there are improvements via the Ampere GA10x architecture that allows for two compute workloads simultaneously. Relative to the example above, this means that we could see a 3x improvement if we were to use one GRAPHICS queue and two COMPUTE queue (together with the extra performance using the TRANSFER queue for transfer operations).&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Congratulations, you’ve made it all the way to the end! Although there was a broad range of topics covered in this post, there is a massive amount of concepts that were skimmed through. These include the underlying Vulkan concepts, GPU computing fundamentals, and more advanced Kompute concepts. Luckily, there are resources online to expand your knowledge on each of these. Here are some links I recommend for further reading:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;“&lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Machine Learning in Mobile &amp;#x26; Cross-Vendor GPUs Made Simple With Kompute &amp;#x26; Vulkan&lt;/a&gt;” article with a deeper dive in theory and concepts&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://axsaucedo.github.io/vulkan-kompute/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Documentation&lt;/a&gt; for more details and further examples&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Machine Learning in Mobile &amp;#x26; Cross-Vendor GPUs Made Simple With Kompute &amp;#x26; Vulkan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://towardsdatascience.com/gpu-accelerated-machine-learning-in-your-mobile-applications-using-the-android-ndk-vulkan-kompute-1e9da37b7617&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Supercharging your Mobile Apps with GPU Accelerated Machine Learning using the Android NDK &amp;#x26; Kompute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://towardsdatascience.com/supercharging-game-development-with-gpu-accelerated-ml-using-vulkan-kompute-the-godot-game-engine-4e75a84ea9f0&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GPU Accelerated ML using the Godot Engine and Kompute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vulkan-tutorial.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Vulkan SDK Tutorial&lt;/a&gt; for a deep dive into the underlying Vulkan components&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded><category>gpu</category><category>kompute</category><category>parallel-computing</category></item><item><title>Supercharging your Mobile Apps: GPU Accelerated Machine Learning using Android NDK &amp; Vulkan Kompute</title><link>https://ethical.institute/blog/gpu-accelerated-machine-learning-android/</link><guid isPermaLink="true">https://ethical.institute/blog/gpu-accelerated-machine-learning-android/</guid><description>A hands on tutorial that teaches you how to leverage your on-device phone GPU for accelerated data processing and machine learning using the Android NDK, Kompute and Vulkan.</description><pubDate>Mon, 05 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;Kompute in Android NDK (Image by Author)&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Some smartphones nowadays pack laptop-level hardware — carrying up to 16GB RAM, high-speed multi-core CPUs, and GPUs that can render high-performance complex graphical applications on 4k displays.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Image by Author&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Tapping into that power — especially the GPU processing power — for on-device data processing capabilities becomes growingly important as mobile hardware &lt;a href=&quot;https://www.mobilemarketer.com/news/mobile-games-sparked-60-of-2019-global-game-revenue-study-finds/569658/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;only continues to improv&lt;/a&gt;e. Recently, this has been opening exciting opportunities around &lt;a href=&quot;https://en.wikipedia.org/wiki/Edge_computing&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;edge computing&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Federated_architecture&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;federated architectures&lt;/a&gt;, &lt;a href=&quot;https://arxiv.org/abs/1910.06663&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;mobile deep learning&lt;/a&gt;, and more.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This article provides a technical deep dive that shows you how to tap into the power of mobile cross-vendor GPUs. You will learn how to use the &lt;a href=&quot;https://developer.android.com/ndk&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Android Native Development Kit&lt;/strong&gt;&lt;/a&gt;and the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute framework&lt;/strong&gt;&lt;/a&gt; to write GPU optimized code for Android devices. The end result will be a mobile app created in Android Studio that is able to use a GPU accelerated machine learning model which we will write from scratch, together with a user interface that will allow the user to send the input to the model.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Android Studio Running Project in Emulator (Image by Author)&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;No background knowledge &lt;strong&gt;beyond programming experience&lt;/strong&gt; is required, however if you are curious about the underlying AI / GPU compute concepts referenced, we suggest checking out our previous article, “&lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Machine Learning in Mobile &amp;#x26; Cross-Vendor GPUs Made Simple With Kompute &amp;#x26; Vulkan&lt;/a&gt;”.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can find the full code in the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/master/examples/android/android-simple&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;example folder in the repository&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;android-native-development-kit-ndk&quot;&gt;Android Native Development Kit (NDK)&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Android NDK Diagram (Image by Author)&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The &lt;a href=&quot;https://developer.android.com/ndk&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Native Development Kit (NDK)&lt;/a&gt; is one of Android’s solution to address the increasing computational demands from mobile apps. The NDK framework enables developers to write low level, highly efficient C and C++ code that can interoperate with the Java/Kotlin application code through the popular &lt;a href=&quot;https://en.wikipedia.org/wiki/Java_Native_Interface&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Java Native Interface&lt;/strong&gt;&lt;/a&gt;bindings.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This tooling enables mobile application developers not only to write highly efficient code, but also leverage existing optimized frameworks written in C++ for advanced data processing or machine learning.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;enter-kompute--the-vulkan-sdk&quot;&gt;Enter Kompute &amp;#x26; the Vulkan SDK&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Playing “where’s waldo” with Khronos Membership (Image by Vincent Hindriksen via &lt;a href=&quot;https://streamhpc.com/blog/2017-05-04/what-is-khronos-as-of-today/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;StreamHPC&lt;/a&gt;)&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Vulkan&lt;/strong&gt;is an Open Source project led by the &lt;a href=&quot;https://www.khronos.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Khronos Group&lt;/a&gt;, a consortium consisting of several tech companies who have come together to work towards defining and advancing the open standards for mobile and desktop media (and compute) technologies.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;A large number of high profile (and new) frameworks have been adopting Vulkan as their core GPU processing SDK. The Android NDK’s main documentation page has a full section &lt;a href=&quot;https://developer.android.com/ndk/guides/graphics&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;dedicated to Vulkan&lt;/strong&gt;&lt;/a&gt;, together with hands on examples showing how it can be used in Android mobile devices.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you can imagine, the Vulkan SDK provides very low-level access to GPUs, which allows for very specialized optimizations. This is a great asset for data processing and GPU developers — the main disadvantage is the verbosity involved, requiring 500–2000+ lines of code to only get the base boilerplate required to even start writing the application logic. This can result in expensive developer cycles and errors that can lead to larger problems. This was one of the main motivations for us to start the &lt;strong&gt;Kompute&lt;/strong&gt;project.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute#vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute&lt;/strong&gt;&lt;/a&gt; is a framework built on top of the Vulkan SDK which abstracts a lot of boilerplate code required, introducing best practices that expose Vulkan’s computing capabilities. Kompute is the GPU computing framework that we will be using in this tutorial to build the machine learning module in our mobile Android app.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Kompute &lt;a href=&quot;https://ethicalml.github.io/vulkan-kompute/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Documentation&lt;/a&gt; (Image by Author)&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;machine-learning-in-mobile-development&quot;&gt;Machine Learning in Mobile Development&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this post we will be building upon the Machine Learning use-case we created in the “&lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Machine Learning in Mobile &amp;#x26; Cross-Vendor GPUs Made Simple With Kompute &amp;#x26; Vulkan&lt;/a&gt;” article. We will not be covering the underlying concepts in as much detail as in that article, but we’ll still introduce the high level intuition required in this section.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;To start with, we will need an interface that allows us to expose our Machine Learning logic, which will require primarily two functions:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;train(…)&lt;/code&gt;— function which will allow the machine learning model to learn to predict outputs from the inputs provided&lt;/li&gt;
&lt;li&gt;&lt;code&gt;predict(...)&lt;/code&gt;— function that will predict the output of an unknown instance.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;This can be visualised in the two workflows outlined in the image below.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Data Science Process (Image by Author)&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Particularly in app development, this would also be &lt;a href=&quot;https://www.forbes.com/sites/forbestechcouncil/2020/08/03/how-machine-learning-is-powering-a-new-generation-of-app-development/#17c728f62a88&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;a common pattern&lt;/a&gt; for machine learning workflows, for both predictive and explanatory modelling use cases. This often consists of leveraging data generated by your users as they interact directly (or indirectly) with the app itself. This data can then serve as training features for machine learning models. Training of new models can be performed through manual “offline” workflows that data scientists would carry out, or alternatively through automated triggers retraining models.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;android-studio-project-overview&quot;&gt;Android Studio Project Overview&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Project File Structure (Image by Author)&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will start by providing a high level overview of the core components in the Android Studio project, including the Kompute C++ bindings, the Android User Interface, the App logic build in Kotlin, and the build files required. If you are interested in a particular area you can jump to its respective section below.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You will need to make sure you install &lt;a href=&quot;https://developer.android.com/studio&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Android Studio&lt;/strong&gt;&lt;/a&gt;, and also install the &lt;a href=&quot;https://developer.android.com/ndk/guides#download-ndk&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Android NDK&lt;/strong&gt;&lt;/a&gt;— the rest of the dependencies will be installed and configured automatically when opening the project in the IDE.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that you have everything installed, you are able to import the project. For this, you first have to clone the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;full Kompute repository&lt;/strong&gt;&lt;/a&gt; and import the Android Studio project under &lt;code&gt;examples/android/android-simple/&lt;/code&gt;. You should now be able to see the project load and configure the build. Once it opens you are able to run it in an emulator or in your own physical Android phone. This project was tested in the Pixel 2 emulator, and in a physical Samsung Galaxy phone.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Final GPU Accelerated Kompute App (Image by Author)&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;When you load the project you will notice the following key components in the file structure, which we will be breaking down further in detail in the following sections:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;Android SDK Application&lt;/strong&gt;— The Android UI, asset resources, build files, and Kotlin/Java components that provide the relevant application logic that interacts with the UI and C++ Kompute ML bindings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Android NDK Kompute ML Module&lt;/strong&gt;— The Kompute ML C++ code and bindings configured through Android NDK for GPU accelerated processing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;android-sdk-application&quot;&gt;Android SDK Application&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;This section covers the Android SDK Java/Kotlin and User Interface components, which should provide an intuition on how the high level business logic interacts with the native C++ JNI bindings.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The user interface consists primarily of input text boxes and display text labels to enable users to interact with the GPU Accelerated ML processing C++ core (as shown in the screenshot below). If you are curious on exactly the views used, you can inspect it in your Android Studio project, or directly open the &lt;code&gt;activity_kompute_jni.xml&lt;/code&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/res/layout/activity_kompute_jni.xml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;file&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The core of our mobile app can be found in the &lt;code&gt;app/src/main/java/com/ethicalml/kompute&lt;/code&gt; folder, inside the &lt;code&gt;KomputeJni.kt&lt;/code&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/java/com/ethicalml/kompute/KomputeJni.kt&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;file&lt;/a&gt;. This Kotlin file contains the main business logic for our Android app.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;If we look at the shortened version of the class in the code block below we will notice the following key points:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;kotlin&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// imports&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeJni&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AppCompatActivity&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    override&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onCreate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(savedInstanceState: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Bundle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;?) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeButtonOnClick&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(v: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;View&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    external&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initVulkan&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(): &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    external&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kompute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, xj: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;): &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    external&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; komputeParams&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, xj: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;): &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    companion&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; object&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        init&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            System.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;loadLibrary&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;kompute-jni&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;fun onCreate(…)&lt;/code&gt; — This function is called on initialisation of the Android Activity (when the app is loaded)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fun KomputeButtonOnClick(…)&lt;/code&gt;— This function is triggered when the main “KOMPUTE” button gets pressed, and triggers the C++ Jni binding functions using the data from the user interface text boxes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;external fun initVulkan(): Boolean&lt;/code&gt; — This function is one of the C++ JNI functions that will be bound to the Vulkan initialisation C++ function.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;external fun kompute(...): FloatArray&lt;/code&gt; — The is the C++ JNI function that will train the ML model and run inference on the inputs provided, returned the inference results.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;external fun komputeParams(...): FloatArray&lt;/code&gt; — The C++ JNI function that trains the model and returns the learned parameters &lt;code&gt;weight 1&lt;/code&gt; , &lt;code&gt;weight 2&lt;/code&gt; and &lt;code&gt;bias&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;&lt;code&gt;companion object { ...(&quot;kompute-jni&quot;) }&lt;/code&gt; — This is the name you will give to your C++ output shared library, which will contain the compiled C++ source with all relevant binding functions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you will also notice, the &lt;code&gt;external fun&lt;/code&gt; functions do not have any definition — this is because the definition is provided in the C++ JNI function bindings, which will be covered in the &lt;a href=&quot;http://jni/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;C++ JNI bindings section&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now to cover each of the functions in more detail, we start with the &lt;code&gt;onCreate&lt;/code&gt; function. This function is in charge of initialising all relevant components in our application. This includes:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;val binding&lt;/code&gt; — This is the main object that will allow us to access all the text boxes and elements in the UI.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;val successVulkanInit = initVulkan()&lt;/code&gt; — This is our first call to a C++ JNI function, which is primarily in charge of initialising Vulkan. If it’s successful it returns &lt;code&gt;true&lt;/code&gt;, and we display the respective success message in a &lt;code&gt;android.widget.Toast&lt;/code&gt; popup — an error is displayed otherwise.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;kotlin&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... prior code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeJni&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AppCompatActivity&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    override&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onCreate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(savedInstanceState: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Bundle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;?) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        super&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onCreate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(savedInstanceState)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ActivityKomputeJniBinding.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inflate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(layoutInflater)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        setContentView&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(binding.root)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        binding.komputeGifView.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;loadUrl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;file:///android_asset/komputer-2.gif&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        binding.komputeGifView.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getSettings&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setUseWideViewPort&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        binding.komputeGifView.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getSettings&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setLoadWithOverviewMode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; successVulkanInit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initVulkan&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (successVulkanInit) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            Toast.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;makeText&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(applicationContext, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Vulkan Loaded SUCCESS&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Toast.LENGTH_SHORT).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            binding.KomputeButton.isEnabled &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            Toast.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;makeText&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(applicationContext, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Vulkan Load FAILED&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Toast.LENGTH_SHORT).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;KomputeJni&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Vulkan Result: &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; successVulkanInit)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        binding.predictionTextView.text &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;N/A&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Next up we have the &lt;code&gt;KomputeButtonOnClick(...)&lt;/code&gt; function. This function gets triggered when the user presses the &lt;code&gt;“KOMPUTE”&lt;/code&gt; button in the app. The main purpose of this function is to retrieve the inputs from the input text boxes in the UI, then use the input data to perform an ML train/inference step through the JNI C++ bindings, and finally display the resulting outputs back in the UI text labels. In further detail:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;kotlin&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... prior code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeButtonOnClick&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(v: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;View&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xiEditText &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; findViewById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;EditText&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(R.id.XIEditText)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xjEditText &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; findViewById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;EditText&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(R.id.XJEditText)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yEditText &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; findViewById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;EditText&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(R.id.YEditText)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wOneEditText &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; findViewById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TextView&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(R.id.wOneTextView)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wTwoEditText &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; findViewById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TextView&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(R.id.wTwoTextView)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; biasEditText &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; findViewById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TextView&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(R.id.biasTextView)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; komputeJniTextview &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; findViewById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TextView&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(R.id.predictionTextView)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xi &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xiEditText.text.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;removeSurrounding&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;[&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;]&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { it.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toFloat&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() }.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toFloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xj &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xjEditText.text.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;removeSurrounding&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;[&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;]&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { it.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toFloat&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() }.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toFloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yEditText.text.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;removeSurrounding&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;[&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;]&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { it.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toFloat&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() }.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toFloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kompute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi, xj, y)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;KomputeJni&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RESULT:&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;KomputeJni&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, out.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;contentToString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        komputeJniTextview.text &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; out.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;contentToString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        val&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; komputeParams&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi, xj, y)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;KomputeJni&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Params:&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;KomputeJni&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, params.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;contentToString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        wOneEditText.text &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        wTwoEditText.text &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        biasEditText.text &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;val &amp;#x3C;elementname&gt; = findViewById&amp;#x3C;EditText&gt;(R.id.&amp;#x3C;elementname&gt;)&lt;/code&gt;— This is the format of the steps that create the variable that holds the respective text box with inputs. In this case &lt;code&gt;&amp;#x3C;elementname&gt;&lt;/code&gt; is the name of the element we are interacting with.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xi, xj and y&lt;/code&gt; — The &lt;code&gt;FloatArray&lt;/code&gt; elements created from the text in the respective input boxes, which are then used for the ML model processing.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;val out = kompute(xi, xj, y)&lt;/code&gt; — Here we run the C++ JNI Binding function &lt;code&gt;kompute&lt;/code&gt; which trains and processes the data through the KomputeModelML class we create in C++.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;val params = komputeParams(xi, xj, y)&lt;/code&gt; — Here we run the C++ JNI Binding function which trains and returns the learned parameters of the Kompute machine learning model.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;#x3C;elementname&gt;.text = &amp;#x3C;value&gt;&lt;/code&gt; — The lines that follow this format basically override the text labels in the UI to display the outputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;The last few functions are only explicitly set as external functions to be bound to the C++ JNI bindings. Furthermore the &lt;code&gt;companion object&lt;/code&gt; section provides the name of the shared library that will contain the respective bindings referenced in this activity.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;kotlin&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... prior code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    external&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initVulkan&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(): &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    external&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kompute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, xj: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;): &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    external&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; komputeParams&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, xj: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;): &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FloatArray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    companion&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; object&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        init&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            System.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;loadLibrary&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;kompute-jni&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can find the full file in the &lt;code&gt;KomputeJni.kt&lt;/code&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/java/com/ethicalml/kompute/KomputeJni.kt&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;file&lt;/a&gt; in the repository.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;android-ndk-kompute-ml-module&quot;&gt;Android NDK Kompute ML Module&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;This section covers the &lt;strong&gt;Android NDK Kompute ML Module&lt;/strong&gt; files, which includes the build-system, and the C++ source code using the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute framework&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Kompute &lt;a href=&quot;https://ethicalml.github.io/vulkan-kompute/overview/reference.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Architecture Design&lt;/a&gt; (Image by Author)&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will be using the core components of Kompute which are outlined in this accompanying diagram. Namely, we will be loading the relevant data in the GPU using Kompute Tensors, processing it with the respective Kompute Operations, and orchestrating this with a Kompute Sequence and a Kompute Manager. We won’t be covering the Kompute architecture in detail but if you want to learn more about the underlying concepts, you can check out the more detailed article on &lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the underlying implementation&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The core components in the Android NDK bindings module consist of the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;strong&gt;JNI Binding Functions&lt;/strong&gt; — The native functions that can be called from the Java/Kotlin Android SDK application code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;KomputeModelML Class&lt;/strong&gt; — The class that exposes the Kompute GPU Accelerated ML model logic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CMake build file&lt;/strong&gt;— The C++ build file responsible for compiling and linking all relevant libraries.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;jni-binding-functions&quot;&gt;JNI Binding Functions&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The JNI bindings in this case are provided via the &lt;code&gt;KomputeJniNative.cpp&lt;/code&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/cpp/KomputeJniNative.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;file&lt;/a&gt;. The skeleton of the class is below — the function code logic has been redacted for simplicity, and will be explained in more detail below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Imports &amp;#x26; util functions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;extern&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;C&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;JNIEXPORT jboolean JNICALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Java_com_ethicalml_kompute_KomputeJni_initVulkan&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(JNIEnv &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env, jobject thiz) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;JNIEXPORT jfloatArray JNICALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Java_com_ethicalml_kompute_KomputeJni_kompute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        JNIEnv &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jobject thiz,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray xiJFloatArr,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray xjJFloatArr,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray yJFloatArr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;JNIEXPORT jfloatArray JNICALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Java_com_ethicalml_kompute_KomputeJni_komputeParams&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        JNIEnv &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jobject thiz,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray xiJFloatArr,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray xjJFloatArr,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray yJFloatArr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The JNI binding functions have to match the class functions defined in the Java/Kotlin code. The format for the function is:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;Java_&amp;#x3C;modulepath&gt;_&amp;#x3C;class&gt;_&amp;#x3C;functionname&gt;(env, thiz, ...params)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;In our case the class is in the &lt;code&gt;com.ethicalml.kompute&lt;/code&gt; module, in the class &lt;code&gt;KomputeJni&lt;/code&gt; and its respective function — below the name of the functions will reflect this structure.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Diving one level deeper, we can now go through each section of the file. Starting with the imports, we can see below the imports together with comments outlining their core functionality.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Includes the Jni utilities for Android to be able to create the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// relevant bindings for java, including JNIEXPORT, JNICALL , and&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// other &quot;j-variables&quot;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#x3C;jni.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// The ML class exposing the Kompute ML workflow for training and&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// prediction of inference data.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;KomputeModelML.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Allows us to use the C++ sleep function to wait when loading the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Vulkan library in android&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#x3C;unistd.h&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;In Android applications, we actually need to initialize the Vulkan dynamic library manually (which is something that you normally wouldn’t do outside of Android). The reason why this is required, is because the Vulkan library is not actually linked in Android phones. The reason why Android avoids doing any linking is for backwards compatibility, mainly to ensure the app doesn’t crash if the Vulkan library is not found in older phones.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This means we need to manually find the library in the C++ code and if found, link each function to its respective memory address pointer so our C++ framework can use it. Fortunately, this is something that Kompute does automatically, and we won’t be covering the details in this article as it probably would require an article in itself, but if you’re interested you can read more about it in &lt;a href=&quot;https://marcelbraghetto.github.io/a-simple-triangle/2019/06/16/part-17/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;this post&lt;/strong&gt;&lt;/a&gt;, and you can see how Kompute imports Vulkan dynamically in the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/45ddfe524b9ed63c5fe1fc33773c8f93a18e2fac/src/include/kompute/Core.hpp#L5&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Core.hpp header file&lt;/a&gt; using the &lt;code&gt;vk_ndk_wrapper_include&lt;/code&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/45ddfe524b9ed63c5fe1fc33773c8f93a18e2fac/vk_ndk_wrapper_include&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;files&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Below you can see the implementation of the function that exposes the &lt;code&gt;initVulkan&lt;/code&gt; logic—&lt;code&gt;Java_com_ethicalml_kompute_KomputeJni_initVulkan(...)&lt;/code&gt;. You can see inside this function we run &lt;code&gt;InitVulkan()&lt;/code&gt;until the Vulkan library is successfully initialised, or alternatively fails if the maximum number of retries is reached.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;JNIEXPORT jboolean JNICALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Java_com_ethicalml_kompute_KomputeJni_initVulkan&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(JNIEnv &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env, jobject thiz) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    SPDLOG_INFO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Initialising vulkan&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    uint32_t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; totalRetries &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (totalRetries &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; KOMPUTE_VK_INIT_RETRIES) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        SPDLOG_INFO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;VULKAN LOAD TRY NUMBER: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%u&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, totalRetries);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;InitVulkan&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            break&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        sleep&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        totalRetries&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; totalRetries &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; KOMPUTE_VK_INIT_RETRIES;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once Vulkan has been initialised, it is possible to call the remaining functions. The first one is the &lt;code&gt;kompute&lt;/code&gt; function, which is in charge of training the model and running an inference request. The function receives the input Xi and Xj values, together with the expected predictions that the model will learn from. It will then return the prediction treating Xi and Xj as unseen data. The function will basically call the &lt;code&gt;KomputeModelML&lt;/code&gt; class &lt;code&gt;train&lt;/code&gt; function and &lt;code&gt;predict&lt;/code&gt; function.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;JNIEXPORT jfloatArray JNICALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Java_com_ethicalml_kompute_KomputeJni_kompute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        JNIEnv &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jobject thiz,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray xiJFloatArr,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray xjJFloatArr,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray yJFloatArr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    SPDLOG_INFO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Creating manager&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xiVector &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; jfloatArrayToVector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(env, xiJFloatArr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xjVector &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; jfloatArrayToVector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(env, xjJFloatArr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yVector &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; jfloatArrayToVector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(env, yJFloatArr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    KomputeModelML kml;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    kml.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;train&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(yVector, xiVector, xjVector);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pred &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kml.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;predict&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xiVector, xjVector);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; vectorToJFloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(env, pred);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The last remaining JNI function that will be exposed to the Java/Kotlin code is the &lt;code&gt;komputeParams&lt;/code&gt; function, which is in charge of returning the parameters that the machine learning model learns, namely the &lt;code&gt;weight 1&lt;/code&gt; , &lt;code&gt;weight 2&lt;/code&gt; and the &lt;code&gt;bias&lt;/code&gt; parameters.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;JNIEXPORT jfloatArray JNICALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Java_com_ethicalml_kompute_KomputeJni_komputeParams&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        JNIEnv &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jobject thiz,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray xiJFloatArr,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray xjJFloatArr,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        jfloatArray yJFloatArr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    SPDLOG_INFO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Creating manager&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xiVector &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; jfloatArrayToVector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(env, xiJFloatArr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xjVector &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; jfloatArrayToVector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(env, xjJFloatArr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yVector &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; jfloatArrayToVector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(env, yJFloatArr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    KomputeModelML kml;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    kml.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;train&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(yVector, xiVector, xjVector);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;float&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kml.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get_params&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; vectorToJFloatArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(env, params);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The only remaining functions are the utility functions that we used in the JNI logic — namely &lt;code&gt;jfloatArrayToVector&lt;/code&gt; and &lt;code&gt;vectorToJFloatArray&lt;/code&gt; — these functions are self explanatory, so we’ll leave it to the reader to explore further in the source if interested.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;komputemodelml-class&quot;&gt;KomputeModelML Class&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we’ve covered the key functions that are bound to the Kotlin / Java class, we can cover the &lt;code&gt;KomputeModelML&lt;/code&gt; C++ class that contains the Kompute GPU Accelerated logic.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The header file for the KomputeModelML class is outlined below, and contains the following key components:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#pragma&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; once&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;kompute/Kompute.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeModelML&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;public:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    KomputeModelML&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    virtual&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ~KomputeModelML&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; train&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;yData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;xIData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;xJData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;predict&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;xI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;xJ&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get_params&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;private:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor mWeights;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor mBias;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::string LR_SHADER &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; R&quot;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;//... rest of header file&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;#include &quot;kompute/Kompute.hpp”&lt;/code&gt; — header containing all the Kompute dependencies that we’ll use in this project&lt;/li&gt;
&lt;li&gt;&lt;code&gt;void train(...)&lt;/code&gt; —Trains the machine learning model using the GPU native code for the logistic regression model. It takes the input array(s) &lt;code&gt;X&lt;/code&gt;, and the array &lt;code&gt;y&lt;/code&gt;containing the expected outputs.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;std::vector&amp;#x3C;float&gt; predict(...)&lt;/code&gt; —Perform the inference request. In this implementation it is not using GPU code as generally there tends to be less performance gains through parallelization on the inference side. However there are still expected performance gains if multiple inputs are processed in parallel (which this function allows for).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;std::vector&amp;#x3C;float&gt; get_params()&lt;/code&gt; —Returns an array containing the learned parameters in the format of &lt;code&gt;[ &amp;#x3C;weight_1&gt;, &amp;#x3C;weight_2&gt;, &amp;#x3C;bias&gt; ]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;static std::string LR_SHADER&lt;/code&gt;— The &lt;a href=&quot;https://en.wikipedia.org/wiki/OpenGL_Shading_Language&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;shader code that will be executed as machine code inside of the GPU&lt;/a&gt;. Kompute allows us to pass a string containing the code, however for production deployments it is possible to convert the shaders to binary, and also use the utilities available to convert into header files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you are interested in the full implementation you can find all the files in &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/v0.3.2/examples/android/android-simple&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the repository&lt;/a&gt;. Furthermore if you are interested in the theoretical and underlying foundational concepts of these techniques, this is covered fully in &lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a#6c88&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;our previous post&lt;/a&gt;.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;cmake-build-file&quot;&gt;CMake Build File&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;The &lt;code&gt;CMakeLists.txt&lt;/code&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/v0.3.2/examples/android/android-simple/app/src/main/cpp/CMakeLists.txt&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;build file&lt;/strong&gt;&lt;/a&gt; is a very important component in the Android NDK workflow. This section becomes particularly important if you wish to add Kompute into your own project. The cmake file is quite small so we’ll be covering each of the lines separately.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;First we need to make sure the Kompute library is available. Usually you would run the &lt;code&gt;INSTALL&lt;/code&gt;target of the Kompute build to be able to use/import the respective library. However in this case we need to make sure Kompute is built for the right Android CPU architecture —our simplest option is adding the main repository as part of the build, which means that Kompute will also be built for the right mobile architectures. If you want to include this in your project, you just need to make sure the path is relative to the Kompute cloned folder.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cmake&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;add_subdirectory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ../../../../../../../&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    ${CMAKE_CURRENT_BINARY_DIR}&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/kompute_build)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We now set the variable VK_ANDROID_INCLUDE_DIR to the vulkan include directory. This contains all the include files we need for Vulkan — for completeness, Kompute uses the &lt;code&gt;vulkan.h&lt;/code&gt; header as well as the &lt;code&gt;vulkan.hpp&lt;/code&gt; C++ headers.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cmake&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  VK_ANDROID_INCLUDE_DIR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  ${ANDROID_NDK}&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sources&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/third_party/vulkan/src/include)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We are now able to add the library that will be used by the Java/Kotlin Android Studio project, which in this case is the shared library &lt;code&gt;kompute-jni&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cmake&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;add_library&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(kompute-jni SHARED&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        KomputeJniNative.cpp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        KomputeModelML.cpp)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We now are able to add all relevant &lt;code&gt;include&lt;/code&gt; directories. This includes the &lt;code&gt;VK_ANDROID_INCLUDE_DIR&lt;/code&gt;which we defined above, as well as the &lt;code&gt;VK_ANDROID_COMMON_DIR&lt;/code&gt; which contains Android &lt;code&gt;log.h&lt;/code&gt; . The &lt;code&gt;single_include&lt;/code&gt; is what contains the &lt;code&gt;kompute/Kompute.hpp&lt;/code&gt; header from Kompute. Finally, we need to import the Kompute Dynamic library wrapper &lt;code&gt;vk_ndk_wrapper_include&lt;/code&gt; which is necessary as the Vulkan library is imported dynamically. The logic behind this could become a series of articles in itself, so we won’t go down this rabbit-hole, but if you’re interested you can read more in &lt;a href=&quot;https://marcelbraghetto.github.io/a-simple-triangle/2019/06/16/part-17/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;this post&lt;/strong&gt;&lt;/a&gt;, and you can see how Kompute imports &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/blob/45ddfe524b9ed63c5fe1fc33773c8f93a18e2fac/src/include/kompute/Core.hpp#L5&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Vulkan dynamically&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cmake&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;include_directories&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        ${VK_ANDROID_COMMON_DIR}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        ${VK_ANDROID_INCLUDE_DIR}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ../../../../../../../single_include/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ../../../../../../../vk_ndk_wrapper_include/)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;To compile the project we’ll want to make sure the &lt;code&gt;VK_USE_PLATFORM_ANDROID_KHR&lt;/code&gt; is set, as this is what enables the Android configuration. For this project we also disable the Vulkan debug layers with &lt;code&gt;KOMPUTE_DISABLE_VK_DEBUG_LAYERS.&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cmake&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;CMAKE_CXX_FLAGS&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;${CMAKE_CXX_FLAGS} -std=c++14 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                     -DVK_USE_PLATFORM_ANDROID_KHR=1 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                     -DKOMPUTE_DISABLE_VK_DEBUG_LAYERS=1&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally, we are able to link the relevant libraries to our &lt;code&gt;kompute-jni&lt;/code&gt; shared library target. This includes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cmake&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;target_link_libraries&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(kompute-jni&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # Libraries from kompute build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        kompute&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        kompute_vk_ndk_wrapper&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # Libraries from android build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        android)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;kompute&lt;/code&gt;— This is the library created in the Kompute build.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kompute_vk_ndk_wrapper&lt;/code&gt; — This library also gets created by the Kompute build and contains the code to dynamically load and wrap the Vulkan library.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;log&lt;/code&gt; — This is the Android log library, which is required by Kompute to override logging.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;android&lt;/code&gt; — This is the Android library which is used by the Android project.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;That’s it — you are now able to run the application, which will execute the full build. You should then be able to see the Kompute app in your Android Studio emulator, or in you physical phone, where you’ll be able to trigger the processing on your on-device GPU.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Android Studio Running Project in Emulator (Image by Author)&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Congratulations, you’ve made it all the way to the end! Although there was a broad range of topics covered in this post, there is a massive amount of concepts that were skimmed through. These include the underlying Android Development workflows, Vulkan concepts, GPU computing fundamentals, machine learning best practices, and more advanced Kompute concepts. Luckily, there are resources online to expand your knowledge on each of these. Here are some links I recommend for further reading:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;“&lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Machine Learning in Mobile &amp;#x26; Cross-Vendor GPUs Made Simple With Kompute &amp;#x26; Vulkan&lt;/a&gt;” article with a deeper dive in theory and concepts&lt;/li&gt;
&lt;li&gt;“&lt;a href=&quot;https://towardsdatascience.com/parallelizing-heavy-gpu-workloads-via-multi-queue-operations-50a38b15a1dc&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Parallelizing GPU-intensive Workloads via Multi-Queue Concurrency using Kompute&lt;/a&gt;” with more advanced Kompute concepts&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://axsaucedo.github.io/vulkan-kompute/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Documentation&lt;/a&gt; for more details and further examples&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ethical.institute/mle.html&quot;&gt;The Machine Learning Engineer Newsletter&lt;/a&gt; if you want to keep updated on articles around Machine Learning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.android.com/ndk/guides&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Android NDK Getting Started Documentation&lt;/a&gt; if you want to dive further into the Native Development Kit&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EthicalML/awesome-production-machine-learning/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Awesome Production Machine Learning&lt;/a&gt; list for open source tools to deploy, monitor, version and scale your machine learning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fast.ai/2018/09/26/ml-launch/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Introduction to ML for Coders course&lt;/a&gt; by FastAI to learn further machine learning concepts&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vulkan-tutorial.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Vulkan SDK Tutorial&lt;/a&gt; for a deep dive into the underlying Vulkan components&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded><category>gpu</category><category>kompute</category><category>machine-learning</category><category>android</category></item><item><title>Beyond CUDA: GPU Accelerated C++ for Machine Learning on Cross-Vendor Graphics Cards Made Simple</title><link>https://ethical.institute/blog/beyond-cuda-gpu-accelerated-cpp/</link><guid isPermaLink="true">https://ethical.institute/blog/beyond-cuda-gpu-accelerated-cpp/</guid><description>A hands on introduction into GPU computing with practical machine learning examples using the Kompute Framework and the Vulkan SDK.</description><pubDate>Sat, 12 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;Machine learning, together with many other advanced data processing paradigms, fits incredibly well to the parallel-processing architecture that GPU computing offers.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-01.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 2&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Image by &lt;a href=&quot;https://docs.google.com/presentation/d/1WBLcBmk7J04Zu8cD3ugagPkEpKkDuJpNr-HfroNe4X8/edit#slide=id.p&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Author&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this article you’ll learn how to write your own ML algorithm from scratch in GPU optimized code, which will be able to run in virtually any hardware — including your mobile phone. We’ll introduce core GPU &amp;#x26; ML concepts and show how you can use the &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute#vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute framework&lt;/strong&gt;&lt;/a&gt; to implement it in only a handful lines of code.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will be building first a simple algorithm that will multiply two arrays in parallel, which will introduce the fundamentals of GPU processing. We will then write a Logistic Regression algorithm from scratch in the GPU. You can find the repo with the full code in the following links:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GPU Array Multiplication &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/tree/4e3802cb9dbf8742f9caf0374ef1612466c5ab1a/examples/array_multiplication#kompute-array-multiplication-example&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Repository&lt;/a&gt; and &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/blob/4e3802cb9dbf8742f9caf0374ef1612466c5ab1a/examples/array_multiplication/src/Main.cpp#L15&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GPU Logistic Regression &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/tree/7906406dd1e8bbfb01c1c5d68be44f63587440aa/examples/logistic_regression#kompute-logistic-regression-example&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Repository&lt;/a&gt;, &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/blob/7906406dd1e8bbfb01c1c5d68be44f63587440aa/examples/logistic_regression/src/Main.cpp#L15&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Code&lt;/a&gt; and &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/blob/7906406dd1e8bbfb01c1c5d68be44f63587440aa/examples/logistic_regression/shaders/glsl/logistic_regression.comp#L7&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shader Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;The potential and adoption of GPU computing has been exploding in recent years — you can get a glimpse of the increasing speed in adoption from the charts in the image below. In deep learning there has been a massive increase in adoption of GPUs for processing, together with paradigms that have enabled massively parallelizable distribution of compute tasks across increasing number of GPU nodes. There is a lot of exciting research around techniques that propose new approaches towards &lt;a href=&quot;https://mxnet.apache.org/versions/1.7/api/faq/model_parallel_lstm.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;model parallelism&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_parallelism&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;data parallelism&lt;/a&gt;— both which allow algorithms and data respectively to be sub-divided in a broad range of approaches to maximize processing efficiency.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-02.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 3&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;strong&gt;Ben-Nun, Tal, and Torsten Hoefler. “Demystifying parallel and distributed deep learning: An in-depth concurrency analysis.” &lt;em&gt;ACM Computing Surveys (CSUR)&lt;/em&gt; 52.4 (2019): 1–43.&lt;/strong&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this article we outline the theory, and hands on tools that will enable both, beginners and seasoned GPU compute practitioners, to make use of and contribute to the current development and discussions across these fascinating high-performance computing areas.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;the-vulkan-framework&quot;&gt;The Vulkan Framework&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Before diving right in, it is worth introducing the core framework that is making it possible to build hyper-optimized, cross platform and scalable GPU algorithms — and that is the Vulkan Framework.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-03.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 4&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Playing “where’s waldo” with Khronos Membership (Image by Vincent Hindriksen via &lt;a href=&quot;https://streamhpc.com/blog/2017-05-04/what-is-khronos-as-of-today/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;StreamHPC&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Vulkan is an Open Source project led by the &lt;a href=&quot;https://www.khronos.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Khronos Group&lt;/a&gt;, a consortium of a very large number of tech companies who have come together to work towards defining and advancing the open standards for mobile and desktop media (and compute) technologies. On the left you can see the broad range of Khronos Members.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You may be wondering, &lt;em&gt;why do we need yet another new GPU framework where there are already many options available for writing parallelizable GPU code?&lt;/em&gt; The main reason is that unlike some of its closed source counterparts (e.g. NVIDIA’s CUDA, or Apple’s Metal) Vulkan is fully Open Source, and unlike some of the older options (e.g. OpenGL), Vulkan is built with the modern GPU architecture in mind, providing very granular access to GPU optimizations. Finally, whilst some alternatives provide vendor-specific support for GPUs, Vulkan provides &lt;strong&gt;cross-platform&lt;/strong&gt;, and &lt;strong&gt;cross-vendor&lt;/strong&gt; support, which means that it opens the doors to opportunities in mobile processing, edge computing, and more.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The Vulkan SDK provides very low-level access to GPUs, which allows for very specialized optimizations. This is a great asset for GPU developers — the main disadvantage is the verbosity involved, requiring 500–2000+ lines of code to only get the base boilerplate required to even start writing the application logic. This can result not only in expensive developer cycles but also prone to small errors that can lead to larger problems.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This can actually be seen across many new and renowned machine learning &amp;#x26; deep learning projects like Pytorch, Tensorflow, and Alibaba DNN — between others — which have either integrated or are looking to integrate the Vulkan GPU SDK to add mobile GPU (and cross-vendor GPU) support. All of these frameworks end up with very similar and extremely verbose boilerplate code, which means they would have benefited (and could still benefit) from using a unified baseline. This was one of the main motivations for us to start the &lt;strong&gt;Kompute&lt;/strong&gt;project.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;enter-kompute&quot;&gt;Enter Kompute&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute#vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute&lt;/strong&gt;&lt;/a&gt; is a framework built on top of the Vulkan SDK, specifically designed to extend its compute capabilities as a simple to use, highly optimized, and mobile friendly General Purpose GPU computing framework.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-04.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 5&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Kompute &lt;a href=&quot;https://ethicalml.github.io/vulkan-kompute/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Documentation&lt;/a&gt; (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Kompute was not built to hide any of the core Vulkan concepts — the Vulkan API is very well designed —instead it augments Vulkan’s Computing capabilities with a BYOV (bring your own Vulkan) design, enabling developers by reducing boilerplate code required and automating some of the more common workflows involved in writing Vulkan applications.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For new developers curious to learn more, it provides a solid base to get started into GPU computing. For more advanced Vulkan developers, Kompute allows them to integrate it into their existing Vulkan applications, and perform very granular optimizations by getting access to all of the Vulkan internals when required. The project is fully open source, and we welcome bug reports, documentation extensions, new examples or suggestions — please feel free to &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/issues&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;open an issue&lt;/a&gt; in the repo.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;writing-your-first-kompute&quot;&gt;Writing your first Kompute&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;To build our first simple array-multiplication GPU computing application using Kompute, we will create the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Two&lt;strong&gt;Kompute Tensors&lt;/strong&gt;to store the input data&lt;/li&gt;
&lt;li&gt;One &lt;strong&gt;Kompute Tensor&lt;/strong&gt; to store the output data&lt;/li&gt;
&lt;li&gt;A&lt;strong&gt;Kompute Operation&lt;/strong&gt; to create and copy the tensors to the GPU&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Kompute Operation&lt;/strong&gt; with an Kompute Algorithm that will hold the code to be executed in the GPU (called a “shader”)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Kompute Operation&lt;/strong&gt; to sync the GPU data back to the local tensors&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Kompute Sequence&lt;/strong&gt; to record the operations to send to the GPU in batches (we’ll use the&lt;strong&gt;Kompute Manager&lt;/strong&gt;to simplify the workflow)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-05.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 6&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Kompute &lt;a href=&quot;https://ethicalml.github.io/vulkan-kompute/overview/reference.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Architecture Design&lt;/a&gt; (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;At the core of Kompute are “Kompute Operations”, which are used for GPU actions, as well as “Kompute Tensor” operations to handle the GPU data and memory. More specifically, this diagram shows the relationship between Kompute components (including explicit memory ownership).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;When interacting with the GPU, you have to send the instructions to the GPU to execute, and you need to make sure that the GPU has all of the relevant data available in GPU memory to begin processing. With Vulkan you send these instructions to the GPU via a queue, so to simplify things intuitively you can think of your GPU as a remote server, where data serialization, resource creation and memory allocation is expensive, and instructions are submitted via a queue — there is still GPU-CPU shared memory but you tend to only use this for data transfer to the GPU.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s jump into the code. Typically, in a Kompute application we’ll follow the following steps:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;Create a Kompute Manager to manage resources&lt;/li&gt;
&lt;li&gt;Create Kompute Tensors to hold data&lt;/li&gt;
&lt;li&gt;Initialise the Kompute Tensors in the GPU with a Kompute Operation&lt;/li&gt;
&lt;li&gt;Define the code to run on the GPU as a “compute shader”&lt;/li&gt;
&lt;li&gt;Use Kompute Operation to run shader against Kompute Tensors&lt;/li&gt;
&lt;li&gt;Use Kompute Operation to map GPU output data into local Tensors&lt;/li&gt;
&lt;li&gt;Print your results&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-create-a-kompute-manager-to-manage-resources&quot;&gt;1. Create a Kompute Manager to manage resources&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;First, we’ll create our Kompute Manager, which is in charge of creating and managing all the underlying Vulkan resources.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Single header include for Kompute&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;kompute/Kompute.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Vulkan resources get created unless passed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Manager &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mgr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // Selects GPU device at index 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued in next section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you can see, here we are initializing our Kompute Manager, expecting it to create all the base Vulkan resources on Device 0 (in my case Device 0 is my NVIDIA card, and Device 1 is my integrated graphics card). For more advanced use-cases it’s also possible to initialize the Kompute Manager with your own Vulkan resources (Device, Queue, etc) but this is out of scope of this article.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-create-kompute-tensors-to-hold-data&quot;&gt;2. Create Kompute Tensors to hold data&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will now create the Kompute Tensors that will be used for input and output. These will hold the data required which will be mapped into the GPU to perform this simple multiplication.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued from previous section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorInA{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }) };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorInB{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }) };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorOut{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }) };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued in next section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued from previous section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; tensorParams&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensorInA},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensorInB},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tensorOut}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued in next section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The reason why Kompute uses &lt;code&gt;std::shared_ptr&lt;/code&gt; by design to avoid passing the objects by value, and instead passing them using &lt;a href=&quot;https://docs.microsoft.com/en-us/cpp/cpp/smart-pointers-modern-cpp?view=vs-2019&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;smart pointers&lt;/a&gt;.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-initialise-the-kompute-tensors-in-the-gpu-with-a-kompute-operation&quot;&gt;3. Initialise the Kompute Tensors in the GPU with a Kompute Operation&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have our Tensors created with local data, we will map the data into the GPU. For this we will use the &lt;code&gt;kp::OpTensorCreate&lt;/code&gt; Kompute Operation, which will initialize the underlying Vulkan buffer and GPU memory, and perform the respective mapping into the GPU.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued from previous section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Create the tensors by passing them as parameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpTensorCreate&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ tensorInA, tensorInB, tensorOut });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued in next section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;It’s also worth mentioning that it’s possible to shorten the tensor creation steps by leveraging the Kompute Manager &lt;code&gt;buildTensor&lt;/code&gt; helper function. This would allow you to skip the need to create the &lt;code&gt;shared_ptr&lt;/code&gt; explicitly as well as the &lt;code&gt;kp::OpTensorCreate&lt;/code&gt; Operation as outlined below (you can also find the full code implementation of &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/blob/2e8a5aa3a6d6172abb51ac038e1b75c5c2d58af9/test/TestMultipleAlgoExecutions.cpp#L274&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;this variation here&lt;/a&gt;).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued from previous section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Using this instead of Operations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorInA &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mgr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;buildTensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorInB &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mgr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;buildTensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorOut &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mgr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;buildTensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued in next section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;4-define-the-code-to-run-on-the-gpu-as-a-compute-shader&quot;&gt;4. Define the code to run on the GPU as a “compute shader”&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we’ve initialized the necessary Kompute Tensor components and they are mapped in GPU memory, we can add the Kompute Algorithm that will be executed in the GPU. This is referred to as the “shader” code, which follows a C-like syntax. You can see the full shader code below, and we’ll break down each of the sections below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued from previous section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Define your shader as a string (using string literals for simplicity)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // (You can also pass the raw compiled bytes, or even path to file)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::string &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;shader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;R&quot;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        // The version to use&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        #version 450&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        // The execution structure&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        layout (local_size_x = 1) in;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        // The buffers are provided via the tensors&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        layout(binding = 0) buffer bufA { float a[]; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        layout(binding = 1) buffer bufB { float b[]; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        layout(binding = 2) buffer bufOut { float o[]; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        void main() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            uint index = gl_GlobalInvocationID.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            o[index] = a[index] * b[index];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    )&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued in next section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The &lt;code&gt;#version 450&lt;/code&gt; and &lt;code&gt;layout(local_size_x = 1) in;&lt;/code&gt; sections specify the version and parallel thread execution structure (which we’ll look at further down the article). We then can see the GPU data inputs and outputs defined in the format:&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;&lt;code&gt;layout(binding = &amp;#x3C;INDEX&gt;) buffer &amp;#x3C;UNIQUENAME&gt; {float &amp;#x3C;VARNAME&gt;[]};&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;index&gt; — index that maps Tensors to the GPU input&lt;/index&gt;&lt;/li&gt;
&lt;li&gt;&lt;uniquename&gt; — This must be a unique name for the buffer&lt;/uniquename&gt;&lt;/li&gt;
&lt;li&gt;&lt;varname&gt; — This is the variable name to use in the shader code&lt;/varname&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;These are the parameters that can be used throughout the shader code for processing. Namely in this case, the processing is done inside the &lt;code&gt;main&lt;/code&gt;function. The first variable &lt;code&gt;uint index = gl_GlobalInvocationID.x;&lt;/code&gt; is the currently parallel execution index which will allow us to process each data input.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We then come into the core of this algorithm which is the multiplication &lt;code&gt;o[index] = a[index] * b[index].&lt;/code&gt;This part is quite self-explanatory — we multiply the elements of the GPU arrays &lt;code&gt;a[]&lt;/code&gt; and &lt;code&gt;b[]&lt;/code&gt; , then store the output on the array &lt;code&gt;o[]&lt;/code&gt;.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;5-use-kompute-operation-to-run-shader-against-kompute-tensors&quot;&gt;5. Use Kompute Operation to run shader against Kompute Tensors&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order to run the shader above we will create the Kompute Operation &lt;code&gt;kp::OpAlgoBase&lt;/code&gt;. The parameters required for this Kompute Operation includes the Tensors to bind into the GPU instructions, as well as the shader code itself.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued from previous section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Run Kompute operation on the Tensor parameters provided&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpAlgoBase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tensorParams,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), shader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued in next section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;It’s worth mentioning that Kompute allows the user to also pass the shader through a file path, or alternatively there are also Kompute tools that will allow you to convert the shader binaries into C++ header files.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;6-use-kompute-operation-to-map-gpu-output-data-into-local-tensors&quot;&gt;6. Use Kompute Operation to map GPU output data into local Tensors&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once the algorithm gets triggered, the result data will now be we held in the GPU memory of our output tensor. We can now use the &lt;code&gt;kp::OpTensorSyncLocal&lt;/code&gt;Kompute Operation to sync the Tensor GPU memory as per the code block below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued from previous section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Run Kompute operation on the parameters provided with dispatch layout&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    mgr.evalOpDefault&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpTensorSyncLocal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ tensorOut });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued in next section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;7-print-your-results&quot;&gt;7. Print your results&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally, we can print the output data of our tensor.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //... continued from previous section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // prints &quot;Output {  0  4  12  }&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::cout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Output: {  &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; float&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elem : tensorOut-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::cout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elem &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::cout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;}&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::endl;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;When you run this, you will see the values of your output tensor printed. That’s it, you’ve written your first Kompute!&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can also find the full example in the repo so you can run it and extend it as desired. You can find the full standalone example in &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/tree/4e3802cb9dbf8742f9caf0374ef1612466c5ab1a/examples/array_multiplication#kompute-array-multiplication-example&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;this repository&lt;/a&gt; which includes the instructions on how to build it as well as the &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/blob/4e3802cb9dbf8742f9caf0374ef1612466c5ab1a/examples/array_multiplication/src/Main.cpp#L15&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute C++ code&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Although it may not seem obvious, the above introduced some intuition around core concepts and design thinking in GPU computing, whilst still abstracting a couple of the more in-depth concepts. In the following sections we will be providing more concrete terminology and we’ll be scratching the surface of some of the more advanced concepts such as threads, blocks, memory strides and shared memory (although a lot will be provided as further reading).&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;diving-into-the-machine-learning-intuition&quot;&gt;Diving into the Machine Learning intuition&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s look at a more advanced GPU compute use-case, specifically implementing the hello world of machine learning, logistic regression. Before we cover the implementation we will provide some intuition on the theory, and the terminology that we’ll be using throughout.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In machine learning we always have two stages, training and inference. In the diagram below you can see the two simplified flows. At the top is the training flow, where you identify some training data, extract some features, and train a model until you are happy with the accuracy. Once you have a trained model, you persist the model “weights” and deploy the model into the second workflow, where the model would perform inference on unseen data.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-06.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 7&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Data Science Process (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case we will have an input dataset &lt;code&gt;X&lt;/code&gt; , where each element is a pair &lt;code&gt;xi&lt;/code&gt; and &lt;code&gt;xj&lt;/code&gt; . Our input data will be the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;xi = { 0, 1, 1, 1, 1 }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xj = { 0, 0, 0, 1, 1 }&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;With this input data, the expected target value &lt;code&gt;Y&lt;/code&gt; to be predicted will be the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;Y = {0, 0, 0, 1, 1}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-07.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 8&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Logistic Regression Example from &lt;a href=&quot;https://www.datasciencecentral.com/profiles/blogs/why-logistic-regression-should-be-the-last-thing-you-learn-when-b&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;DS Central&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Our primary objective in machine learning is to learn using this data to find the function (and parameters) that will allow us to predict values &lt;code&gt;Y&lt;/code&gt; from just using &lt;code&gt;X&lt;/code&gt; as input.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;It’s worth noting that the predicted values are defined as &lt;code&gt;ŷ&lt;/code&gt; , which are specifically the values computed with our inference function, distinct to the “true” or “actual” values of &lt;code&gt;Y&lt;/code&gt; that we defined above.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The functions that we will be using for logistic regression will be the following:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-08.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 9&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s break down this function:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;z&lt;/code&gt; — is our linear mapping function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ŷ&lt;/code&gt; —is the resulting predicted outputs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X&lt;/code&gt;ᵀ —The transpose of the matrix containing our inputs xi and xj&lt;/li&gt;
&lt;li&gt;&lt;code&gt;σ&lt;/code&gt; — The sigmoid function which is covered in more detail below&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;And the parameters that we’ll be looking to learn with our machine learning algorithm are:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;W&lt;/code&gt;— The weights that will be applied to the inputs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;b&lt;/code&gt; — The bias that will be added&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;There is also the surrounding function &lt;code&gt;σ&lt;/code&gt;which is the sigmoid function. This function forces our input to be closer to 0 or 1, which could be intuitively seen as the probability of our prediction to be “true”, and is defined as following:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-09.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 10&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This is now the inference function that will allow us to process predictions from new data points. If we say for example that we have a new unseen set of inputs &lt;code&gt;X = { (0, 1) }&lt;/code&gt;, and we assume that the learned parameters were &lt;code&gt;W = (1, 1), b = 0&lt;/code&gt;after running our machine learning algorithm through our training data (which we’ll do later on), then we’ll be able to run this through our prediction function by substituting the values as follows:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-10.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 11&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case the prediction is &lt;code&gt;0.73...&lt;/code&gt;, which would be a positive prediction. This of course is just to demonstrate what our inference function will look like once we learn the parameters &lt;code&gt;W&lt;/code&gt; and &lt;code&gt;b.&lt;/code&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-11.gif&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 12&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Gradient descent visualized from &lt;a href=&quot;https://mi-academy.com/2018/10/04/the-history-of-gradient-descent/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ML Academy&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The way that we will be learning the parameters is by performing a prediction, calculating the error, and then re-adjusting the weights accordingly. The method used to “re-adjust” the weights based on the “prediction error” will be done by leveraging gradient descent. This will be repeated multiple times to find more accurate parameters.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For this we will need to use the derivatives of each of the formulas. The first one, which is the derivative of our linear mapping function &lt;code&gt;z&lt;/code&gt; is:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;∂z = z(x) - y&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Where the variables are defined as follows:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;∂z&lt;/code&gt; — The derivative of the linear mapping function &lt;code&gt;z(x)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;z(x)&lt;/code&gt; — the result of the linear mapping function applied to input &lt;code&gt;x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;y&lt;/code&gt; — the actual value label expected for that input x&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Similarly the derivatives for w and b respectively are the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;∂w = (x - ∂z)/m&lt;/li&gt;
&lt;li&gt;∂b = ∂z/m&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case &lt;code&gt;m&lt;/code&gt; is the total number of input elements.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will now be able to re-adjust the parameters using the above as follows:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;w = w - θ · ∂w&lt;/li&gt;
&lt;li&gt;b = b - θ · ∂b&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case θ is the learning rate, which as the name suggests controls the ratio by which the parameters will be modified on each iteration. Intuitively, the smaller, the more iterations it will be required for the algorithm to converge, however if the learning is too big, it will overshoot, leading to never being able to converge (from the image above you can imagine it will keep bouncing from side to side never reaching the bottom).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order for us to calculate loss, we will be using the log loss function, known also as cross-entropy loss function. This function is defined as follows:&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-12.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 13&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Log loss (cross entropy loss) function&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-13.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 14&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Intuitive diagram to visualize cost function &lt;a href=&quot;https://machinelearningmastery.com/how-to-score-probability-predictions-in-python/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;from ML Mastery&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The function itself is set up such that the larger the difference between the predicted class and the expected class, the larger the error (you can see how much it punishes if the predicted class is on the complete different label).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The loss function will provide us an idea of the improvement of our algorithm across iterations.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally, one of the most important points here will be the intuition behind how we can leverage the parallel architecture of the GPU to optimize computation. In this case, we’ll be able to do it by processing multiple input parameters at the same time, referred to as a micro-batch, and then re-adjusting the parameters in batch. This is known as data-parallelization, and is one of many techniques available. In the next section we will see how this is implemented, namely passing a mini-batch of inputs, storing the weights, and then re-adjusting them before the next iteration.&lt;/p&gt;
&lt;blockquote data-reveal=&quot;&quot;&gt;
&lt;p&gt;Note: In this post we won’t delve into much detail, nor best practices on machine learning, however at the end of the article we will be listing a broad range of sources for people interested to take their machine learning (or GPU compute) knowledge to the next level.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;machine-learning-gpu-code-implementation&quot;&gt;Machine Learning GPU Code Implementation&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have covered some of the core concepts, we will be able to learn about the implementation of the shader, which is the code that will be executed in the GPU.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;First we need to define all the input and output buffers as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;glsl&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer bxi { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xi&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer bxj { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xj&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer by { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer bwin { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; win&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer bwouti { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wouti&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer bwoutj { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; woutj&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer bbin { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer bbout { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, binding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) buffer blout { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you remember, at the end of the last section we mentioned how we will be leveraging the concept of micro-batches in order to use the parallel architecture of GPU processing. What this means in practice, is that we will be passing multiple instances of X to the GPU to process at a time, instead of expecting the GPU to process it one by one. This is why we see that above we have an array for &lt;code&gt;xi, xj, y, wOuti, wOutj,&lt;/code&gt;and&lt;code&gt;bOut&lt;/code&gt; respectively.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In more detail:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;The input &lt;code&gt;X&lt;/code&gt;as arrays xi and xj will hold the micro-batch of inputs&lt;/li&gt;
&lt;li&gt;The array &lt;code&gt;y&lt;/code&gt;will hold all the expected labels for micro-batch inputs&lt;/li&gt;
&lt;li&gt;The two input weight parameters &lt;code&gt;wini&lt;/code&gt; and &lt;code&gt;woutj&lt;/code&gt; will be used for calculating predictions&lt;/li&gt;
&lt;li&gt;The input parameter &lt;code&gt;b&lt;/code&gt; which will be used for calculating the predictions&lt;/li&gt;
&lt;li&gt;The output weights &lt;code&gt;wouti&lt;/code&gt; and &lt;code&gt;woutj&lt;/code&gt;contains weights and will store the derivative of W for all micro-batches that should be subtracted&lt;/li&gt;
&lt;li&gt;Similarly the output bias array contains the derivatives of &lt;code&gt;b&lt;/code&gt;for all micro-batches that should be subtracted in batch&lt;/li&gt;
&lt;li&gt;Finally &lt;code&gt;lout&lt;/code&gt; contains the output array where losses will be returned&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;We also receive the constant &lt;code&gt;M&lt;/code&gt;, which will be the total number of elements — if you remember this parameter will be used for the calculation of the derivatives. We will also see how these parameters are actually passed into the shader from the C++ Kompute side.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;glsl&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (constant_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; uint&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; M &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; m &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(M);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have all the input and output parameters defined, we can start the &lt;code&gt;main&lt;/code&gt; function, which will contain the implementation of our machine learning training algorithm.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will first start by keeping track of the current index of the global invocation. Since the GPU executes in parallel, each of these runs will be running directly in parallel, so this allows the current execution to consistently keep track of what iteration index is currently being executed.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  uint&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; idx &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; gl_GlobalInvocationID.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We now can start preparing all the variables that we’ll be using throughout the algorithms. All our inputs are buffer arrays, so we’ll want to store them in vec2 and float variables.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    vec2 wCurr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; vec2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(win[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], win[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bCurr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bin[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    vec2 xCurr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; vec2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi[idx], xj[idx]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yCurr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y[idx];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this case we’re basically making explicit the variables that are being used for the current “thread run”. The GPU architecture consists of slightly more nuanced execution structures that involve thread blocks, memory access limitations, etc — however we won’t be covering these in this example.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we get into the more fun part —implementing the inference function. Below we will implement the inference function to calculate ŷ, which involves both the linear mapping function, as well as the sigmoid function.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; sigmoid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; z&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; exp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; inference&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vec2&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;vec2&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; w&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Compute the linear mapping function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; dot&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(w, x) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Calculate the y-hat with sigmoid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yHat &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; sigmoid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(z);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yHat;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yHat &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; inference&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xCurr, wCurr, bCurr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have &lt;code&gt;yHat&lt;/code&gt;, we can now use it to calculate the derivatives (∂z, ∂w and ∂b), which in this case are the derivative of the currently-executed index input element.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dZ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yHat &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yCurr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    vec2 dW &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; m) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xCurr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dZ;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dB &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; m) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dZ;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We can now pass the derivatives as outputs, so the parameters can be re-adjusted for the next iteration.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    wouti[idx] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dW.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    woutj[idx] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dW.y;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    bout[idx] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dB;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally we’re able to calculate the loss and add it to the output &lt;code&gt;lout&lt;/code&gt; array.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; calculateLoss&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; yHat&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(yHat)  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yHat));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    lout[idx] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; calculateLoss&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(yHat, yCurr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;That’s it, we’ve now finished the shader that will enable us to train a Logistic Regression algorithm in the GPU — you can find the &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/blob/7906406dd1e8bbfb01c1c5d68be44f63587440aa/examples/logistic_regression/shaders/glsl/logistic_regression.comp#L7&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;full code for the shader&lt;/a&gt; in the GPU logistic regression &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/tree/7906406dd1e8bbfb01c1c5d68be44f63587440aa/examples/logistic_regression#kompute-logistic-regression-example&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;example repository&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we’ll cover the Kompute code required to run this code against a dataset to train our first model and find the parameters.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;machine-learning-orchestration-from-kompute&quot;&gt;Machine Learning Orchestration from Kompute&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;In order to run the shader we created above in the GPU using Kompute, we will follow the following steps:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;Import Kompute and create our main function&lt;/li&gt;
&lt;li&gt;Create all the Kompute Tensors required&lt;/li&gt;
&lt;li&gt;Create the Kompute Manager and initialize a Kompute Sequence&lt;/li&gt;
&lt;li&gt;Execute the Kompute Tensor GPU initialization via Kompute Sequence&lt;/li&gt;
&lt;li&gt;Record batch algorithm execution in Kompute Sequence&lt;/li&gt;
&lt;li&gt;Iterate 100 times: Run micro-batch execution &amp;#x26; update weights&lt;/li&gt;
&lt;li&gt;Print resulting parameters to use for further inference&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you can see this is more involved than the simpler example we used above. In this case we will use the Kompute Sequence instead of the Kompute Manager directly, as we want to have deeper control on the commands that can be recorded to send in batch to the GPU. We will discuss this in more detail as we cover each of the steps. Let’s get started.&lt;/p&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;1-import-kompute-and-create-our-main-function&quot;&gt;1. Import Kompute and create our main function&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will be importing the single header of Kompute — it’s also possible to use the more granular class-based headers if required. We will also create some of the base configuration variables; namely &lt;code&gt;ITERATIONS&lt;/code&gt; and &lt;code&gt;learningRate&lt;/code&gt; which will be used in latter code blocks.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;kompute/Kompute.cpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  uint32_t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ITERATIONS &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; learningRate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;2-create-all-the-kompute-tensors-required&quot;&gt;2. Create all the Kompute Tensors required&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we’ll be creating all the tensors required. In this sub-section you will notice that we will be referencing all the buffers/arrays that are being used in the shader. We’ll also cover how the order in the parameters passed relates to the way data is bound into the shaders so it’s accessible.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xI{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xJ{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wIn{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wOutI{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wOutJ{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bIn{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bOut{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lOut{ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tensor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We also store them in a parameter vector for easier access:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::vector&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {xI, xJ, y, wIn, wOutI, wOutJ, bIn, bOut, lOut};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;3-create-the-kompute-manager-and-initialize-a-kompute-sequence&quot;&gt;3. Create the Kompute Manager and initialize a Kompute Sequence&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you remember from the previous example, we were able to execute commands directly using the Kompute Manager. However we are able to use the Kompute Sequence resource if we want further granularity to record command batches that can be submitted and loaded into the GPU before processing. For this, we will create a Kompute Manager, then create a Kompute Sequence through it.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // We first create a manager selecting device 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Manager mgr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // We then create a sequence and request the pointer (as it&apos;s provided as a weak_ptr)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Sequence&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sq &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mgr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getOrCreateManagedSequence&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;createTensors&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;4-execute-the-kompute-tensor-gpu-initialization-via-kompute-sequence&quot;&gt;4. Execute the Kompute Tensor GPU initialization via Kompute Sequence&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We can now start by running instructions on GPU resources — namely we will start by initialising and map the Tensors with their respective GPU memory. Here you will see how Kompute Sequences provide you with further granularity on the command execution, but it won’t be until the ML inference section that you will see the flexibility of Kompute Sequence.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Let’s get started by recording commands, namely the OpTensorCreate command, and then evaluating the operation across all the tensors above. This operation will create the respective Vulkan memory/buffer resources.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Being listening for recording sequence&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Register a recording command operation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;record&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpTensorCreate&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Stop listening for recording sequence&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Evaluate the currently recorded sequence&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;eval&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;5-record-batch-algorithm-execution-in-kompute-sequence&quot;&gt;5. Record batch algorithm execution in Kompute Sequence&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this section we will want to clear the previous recordings of the Kompute Sequence and begin recording a set of sequences. You will notice that unlike the previous section, in this case we won’t be running the &lt;code&gt;eval()&lt;/code&gt; straight away as we’ll have to run it multiple times, together with extra commands to re-adjust the parameters.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You will also notice that we will be recording three types of Kompute Operations, namely:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Clear previous commands and begin listening for recording sequence&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Ensure the input vectors are sync in GPU device memory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;record&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpTensorSyncDevice&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({wIn, bIn});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Record the execution of the logistic regression shader&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;record&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpAlgoBase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            params,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;test/shaders/glsl/test_logistic_regression.comp&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Sync the output vectors to device so they can be used for processing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;record&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::OpTensorSyncLocal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({wOutI, wOutJ, bOut, lOut});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Stop listening for recording sequence&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sq-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;kp::OpTensorSyncDevice&lt;/code&gt; — This operation ensures that the Tensors are synchronized with their GPU memory by mapping their local data into the GPU data. In this case, these Tensors use Device-only memory for processing efficiency, so the mapping is performed with a staging Tensor inside the operation (which is re-used throughout the operations for efficiency). Here we’re only wanting to sync the input weights, as these will be updated locally with the respective derivatives.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kp::OpAlgoBase&lt;/code&gt; — This is the Kompute Operation that binds the shader that we wrote above with all the local CPU/host resources. This includes making available the Tensors. It’s worth mentioning that the index of the tensors provided as parameters is the order in which they are mapped in the shaders via their respective bindings (as you can see in the shaders each vector has the format &lt;code&gt;layout(binding = NUMBER)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kp::OpTensorSyncLocal&lt;/code&gt;— This Kompute Operation performs a similar set of instructions as the sync operation above, but instead of copying the data to the GPU memory, it does the converse. This Kompute Operation maps the data in the GPU memory into the local Tensor vector so it’s accessible from the GPU/host. As you can see we’re only running this operation in the output tensors.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;6-iterate-100-times-run-micro-batch-execution--update-weights&quot;&gt;6. Iterate 100 times: Run micro-batch execution &amp;#x26; update weights&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have the command recorded, we can start running executions of these pre-loaded commands. In this case, we will be running the execution of a micro-batch iteration, followed by updating the parameters locally, so they are used in the following iteration.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Iterate across all expected iterations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;size_t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ITERATIONS; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        // Run evaluation of recorded commands&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        sq-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;eval&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        // Update all model parameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;size_t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bOut-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(); j&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            wIn-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; learningRate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wOutI-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[j];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            wIn-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; learningRate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wOutJ-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[j];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            bIn-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; learningRate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bOut-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[j];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from latter blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-reveal=&quot;&quot; id=&quot;7-print-resulting-parameters-to-use-for-further-inference&quot;&gt;7. Print resulting parameters to use for further inference&lt;/h3&gt;
&lt;p data-reveal=&quot;&quot;&gt;We now have a trained logistic regression model, or at least we’ve been able to optimize its respective function to identify suitable parameters. We are now able to print these parameters and use the parameters for inference in unseen datasets.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ...code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::cout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;RESULTS&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::endl;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::cout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;w1: &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wIn-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::endl;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::cout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;w2: &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wIn-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::endl;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::cout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;b: &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bIn-&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::endl;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;And we’re done!&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You are able to find this entire example in the example repository, which you’ll be able to run and extend. You will find all the complete files in the GPU Logistic Regression &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/tree/7906406dd1e8bbfb01c1c5d68be44f63587440aa/examples/logistic_regression#kompute-logistic-regression-example&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;example repo&lt;/a&gt;, including the &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/blob/7906406dd1e8bbfb01c1c5d68be44f63587440aa/examples/logistic_regression/src/Main.cpp#L15&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute C++ Code&lt;/a&gt;, and the &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/blob/7906406dd1e8bbfb01c1c5d68be44f63587440aa/examples/logistic_regression/shaders/glsl/logistic_regression.comp#L7&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shader File&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;what-next&quot;&gt;What next?&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Congratulations, you’ve made it all the way to the end! Although there was a broad range of topics covered in this post, there is a massive amount of concepts that were skimmed through. These include the underlying Vulkan concepts, GPU computing fundamentals, machine learning best practices, and more advanced Kompute concepts. Luckily, there are a broad range of resources online to expand your knowledge on each of these. Some links I recommend as further reading include the following:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://axsaucedo.github.io/vulkan-kompute/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Documentation&lt;/a&gt; for more details and further examples&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ethical.institute/mle.html&quot;&gt;The Machine Learning Engineer Newsletter&lt;/a&gt; if you want to keep updated on articles around Machine Learning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EthicalML/awesome-production-machine-learning/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Awesome Production Machine Learning&lt;/a&gt; list for open source tools to deploy, monitor, version and scale your machine learning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fast.ai/2018/09/26/ml-launch/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Introduction to ML for Coders course&lt;/a&gt; by FastAI to learn further machine learning concepts&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vulkan-tutorial.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Vulkan SDK Tutorial&lt;/a&gt; for a deep dive into the underlying Vulkan components&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded><category>gpu</category><category>kompute</category><category>machine-learning</category></item><item><title>Supercharging Game Development with GPU Accelerated Machine Learning</title><link>https://ethical.institute/blog/supercharging-game-development-gpu-accelerated-machine-learning/</link><guid isPermaLink="true">https://ethical.institute/blog/supercharging-game-development-gpu-accelerated-machine-learning/</guid><description>A hands on tutorial that teaches you how integrate GPU optimized ML code in your game development workflows using the Godot Game Engine and the Kompute framework.</description><pubDate>Sat, 12 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-01.gif&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 2&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Image by Author&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Recently, the world has seen various defining milestones in both, the gaming industry and the AI sector. In only a couple of weeks, we have seen major financial announcements in the gaming industry including &lt;a href=&quot;https://venturebeat.com/2020/09/18/unity-technologies-raises-more-than-1-1-billion-in-ipo-at-12-1-billion-valuation/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Unity’s $1.3 Billion IPO&lt;/a&gt; and &lt;a href=&quot;https://venturebeat.com/2020/08/06/epic-games-unveils-1-78-billion-funding-round-at-17-3-billion-valuation/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Epic Games’ $1.78B Investment&lt;/a&gt;. The AI sector has also been catching up with its hype, reaching a &lt;a href=&quot;https://www.grandviewresearch.com/industry-analysis/artificial-intelligence-ai-market&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;$60+ Billion Market in 2020&lt;/a&gt;, and bringing mind blowing applications in the intersection of AI and Gaming, including &lt;a href=&quot;https://deepmind.com/research/case-studies/alphago-the-story-so-far&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AlphaGo’s famous victory over Champion Lee Sedol&lt;/a&gt;, as well as deep learning powered games such as &lt;a href=&quot;https://play.aidungeon.io/main/landing&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AI Dungeon&lt;/a&gt; (and &lt;a href=&quot;https://en.wikipedia.org/wiki/Artificial_intelligence_in_video_games&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;many more applications&lt;/a&gt;).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;This article provides a technical deep dive into this intersection between the two fields, applied artificial intelligence and game development. We delve specifically into how you can leverage the power of the cross-vendor / mobile GPU frameworks for accelerated processing of machine learning and advanced data processing use-cases.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-02.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 3&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Simple game interface for this tutorial (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this tutorial you’ll learn how to use the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute framework&lt;/strong&gt;&lt;/a&gt; to build GPU optimized code inside the popular open source &lt;a href=&quot;https://github.com/godotengine/godot&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Godot Game Engine&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You will understand how machine learning and advanced GPU compute can be leveraged in game development through the Godot Game engine.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;No background knowledge &lt;strong&gt;beyond programming experience&lt;/strong&gt; is required, but if you are curious about the underlying AI / GPU compute concepts referenced, we suggest checking out our previous article, “&lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Machine Learning in Mobile &amp;#x26; Cross-Vendor GPUs Made Simple With Kompute &amp;#x26; Vulkan&lt;/a&gt;”.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;You can find the full code in the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/master/examples/godot_logistic_regression&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;example folder in the repository&lt;/strong&gt;&lt;/a&gt;, together with the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/master/examples/godot_logistic_regression/gdnative_shared&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;GDNative Library&lt;/strong&gt;&lt;/a&gt; implementation and the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/master/examples/godot_logistic_regression/custom_module&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Godot Custom Module&lt;/strong&gt;&lt;/a&gt; implementation.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-03.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 4&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Image from Godot &lt;a href=&quot;https://github.com/godotengine/godot&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Open Source GitHub Repository&lt;/a&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;With over &lt;a href=&quot;https://github.com/godotengine/godot&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;30k github stars and more than 1k contributors&lt;/a&gt; Godot is the most popular OSS game engine. Godot &lt;a href=&quot;https://www.youtube.com/watch?v=KjX5llYZ5eQ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;caters for 2D and 3D development&lt;/a&gt;, and has been used for a broad range of mobile, desktop, console and web compatible games / applications. Godot is built in C++ making it fast and light — it’s only &lt;a href=&quot;https://godotengine.org/download/windows&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;a 40MB download&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Godot is very intuitive for newcomers through &lt;a href=&quot;https://docs.godotengine.org/en/stable/getting_started/step_by_step/godot_design_philosophy.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;robust design principles&lt;/a&gt;, and support for &lt;a href=&quot;https://docs.godotengine.org/en/stable/getting_started/step_by_step/godot_design_philosophy.html#all-inclusive-package&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;high-level languages&lt;/a&gt;, including its domain-specific-language &lt;a href=&quot;https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_basics.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GdScript&lt;/a&gt; which has a Python-like syntax, making it very easy to adopt. It is also possible to develop using C#, Python, Visual Scripting, C++, etc.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this tutorial we will be building a Game using the editor, using GdScript to trigger the ML training / inference, and C++ to develop the core processing components under-the-hood.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;enter-kompute--the-vulkan-sdk&quot;&gt;Enter Kompute &amp;#x26; the Vulkan SDK&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-04.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 5&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Playing “where’s waldo” with Khronos Membership (Image by Vincent Hindriksen via &lt;a href=&quot;https://streamhpc.com/blog/2017-05-04/what-is-khronos-as-of-today/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;StreamHPC&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Vulkan is an Open Source project led by the &lt;a href=&quot;https://www.khronos.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Khronos Group&lt;/a&gt;, a consortium of a very large number of tech companies who have come together to work towards defining and advancing the open standards for mobile and desktop media (and compute) technologies.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Large number of high profile (and new) frameworks have been adopting Vulkan as their core GPU processing SDK. The Godot Engine itself is working on a major 4.0 update that will &lt;a href=&quot;https://godotengine.org/article/vulkan-progress-report-5&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;bring Vulkan as its core rendering engine&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;As you can imagine, the Vulkan SDK provides very low-level access to GPUs, which allows for very specialized optimizations. This is a great asset for data processing and GPU developers — the main disadvantage is the verbosity involved, requiring 500–2000+ lines of code to only get the base boilerplate required to even start writing the application logic. This can result in expensive developer cycles and errors that can lead to larger problems. This was one of the main motivations for us to start the &lt;strong&gt;Kompute&lt;/strong&gt;project.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute#vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute&lt;/strong&gt;&lt;/a&gt; is a framework built on top of the Vulkan SDK, specifically designed to extend its compute capabilities as a simple to use, highly optimized, and mobile friendly General Purpose GPU computing framework.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-05.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 6&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Kompute &lt;a href=&quot;https://ethicalml.github.io/vulkan-kompute/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Documentation&lt;/a&gt; (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Kompute was not built to hide any of the core Vulkan concepts — the core Vulkan API is very well designed. Instead it augments Vulkan’s computing capabilities with a BYOV (bring your own Vulkan) design, enabling developers by reducing boilerplate code required and automating some of the more common workflows involved in writing Vulkan applications.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For new developers curious to learn more, it provides a solid base to get started into GPU computing. For more advanced Vulkan developers, Kompute allows them to integrate it into their existing Vulkan applications, and perform very granular optimizations by getting access to all of the Vulkan internals when required. The project is fully open source, and we welcome bug reports, documentation extensions, new examples or suggestions — please feel free to &lt;a href=&quot;https://github.com/axsaucedo/vulkan-kompute/issues&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;open an issue&lt;/a&gt; in the repo.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;artificial-intelligence-in-game-development&quot;&gt;Artificial Intelligence in Game Development&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;In this post we will be building upon the Machine Learning use-case we created in the “&lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Machine Learning in Mobile &amp;#x26; Cross-Vendor GPUs Made Simple With Kompute &amp;#x26; Vulkan&lt;/a&gt;” article. We will not be covering the underlying concepts in as much detail as in that article, but we’ll still introduce the high level intuition required in this section.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;To start with, we will need an interface that allows us to expose our Machine Learning logic, which will require primarily two functions:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;train(…)&lt;/code&gt;— function which will allow the machine learning model to learn to predict outputs from the inputs provided&lt;/li&gt;
&lt;li&gt;&lt;code&gt;predict(...)&lt;/code&gt;— function that will predict the output of an unknown instance. This can be visualised in the two workflows outlined in the image below.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-06.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 7&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Data Science Process (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Particularly in game development, this would also be a common pattern for machine learning workflows, for both predictive and explanatory modelling use cases. This often consists of leveraging data generated by your users as they interact directly (or indirectly) with the game itself. This data can then serve as training features for machine learning models. Training of new models can be performed through manual “offline” workflows that data scientists would carry out, or alternatively through automated triggers retraining models.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;machine-learning-project-in-godot&quot;&gt;Machine Learning Project in Godot&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will start by providing a high level overview of how our Kompute bindings will be used in our game in Godot. We will create a simple project and train the ML model we created, which will run in the GPU. In this section we will already have the custom KomputeModelML Godot class accessible — details on how to build it and import it into the godot project are covered in a latter section.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-07.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 8&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;New Project Screen (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;For this we are using &lt;a href=&quot;https://godotengine.org/download&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Godot version &lt;strong&gt;3.2.3 stable&lt;/strong&gt;&lt;/a&gt;. Create a new project and a new 2D scene. You should see a blank project with a top level 2D node, as per the image on the left.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now we’ll be able to start adding resources to our game. We will start by creating a simple UI interface / menu consisting of inputs for the machine learning model that reflects the workflows covered in the previous architecture diagram.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will have two input LineEdit text boxes for the data &lt;code&gt;X_i&lt;/code&gt; and &lt;code&gt;X_j&lt;/code&gt;, and one input LineEdit text box for the &lt;code&gt;Y&lt;/code&gt; expected predictions. The image below shows the node structure used to build the UI. You can also access the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/godot_example/examples/godot_logistic_regression&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;full godot project in the repo&lt;/a&gt; by importing the &lt;code&gt;project.godot&lt;/code&gt; file. The nodes will be referenced to read the input data and display the output predictions (and learned parameters).&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-08.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 9&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will now be able to add the GdScript code in Godot which will allow us to read the inputs, train the model and perform predictions — this script is created under the &lt;code&gt;Parent&lt;/code&gt;node.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Below is the full script that we are using to perform the processing, which is using the &lt;code&gt;KomputeModelML&lt;/code&gt;custom Godot class we build in the next section. We’ll break down each of the different areas of the code below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gdscript&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;extends&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Node2D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xi_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/XIHBoxContainer/LineEdit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xj_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/XJHBoxContainer/LineEdit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/XJHBoxContainer/LineEdit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; preds_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/Panel/VBoxContainer/PredHBoxContainer2/PredictionsLabel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w1_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/Panel/VBoxContainer/PredHBoxContainer/Weight1Label&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w2_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/Panel/VBoxContainer/PredHBoxContainer/Weight2Label&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bias_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/Panel/VBoxContainer/PredHBoxContainer/BiasLabel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_ml&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xi &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str2var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi_node.text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xj &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str2var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xj_node.text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str2var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(y_node.text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeModelML&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    s.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;train&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(y, xi, xj)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; preds &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;predict&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi, xj)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    preds_node.text &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(preds)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get_params&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w1_node.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set_text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w2_node.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set_text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    bias_node.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set_text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;First we define variables to make the referencing of Godot Editor nodes simpler. This can be done with the dollar sign syntax &lt;code&gt;$NODE/PATH&lt;/code&gt; as implemented in the snipped below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gdscript&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;extends&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Node2D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xi_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/XIHBoxContainer/LineEdit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xj_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/XJHBoxContainer/LineEdit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/XJHBoxContainer/LineEdit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; preds_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/Panel/VBoxContainer/PredHBoxContainer2/PredictionsLabel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w1_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/Panel/VBoxContainer/PredHBoxContainer/Weight1Label&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w2_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/Panel/VBoxContainer/PredHBoxContainer/Weight2Label&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bias_node &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;UI/UIVBoxContainer/Panel/VBoxContainer/PredHBoxContainer/BiasLabel&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The &lt;code&gt;compute_ml()&lt;/code&gt; function below contains the logic for the machine learning training and predictions. We start by reading the inputs from the text boxes using the Godot editor node references.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gdscript&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_ml&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xi &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str2var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi_node.text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xj &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str2var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xj_node.text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str2var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(y_node.text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from latter blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We now can create an instance from the C++ class bindings that we will be constructing in the next section. This is the class that exposes the training and prediction functions that we will be using for machine learning inference.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gdscript&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_ml&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # We create an instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kml &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeModelML&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;We now can train our model by passing the inputs and the expected predictions. The ML model underneath is &lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a#6c88&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;a logistic regression model&lt;/a&gt;, which will adjust its internal parameters to fit the inputs and outputs best, resulting in a model that is then able to predict unseen datapoints.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gdscript&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_ml&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # We create an instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    kml.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;train&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(y, xi, xj)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have trained our model, we can perform predictions on unseen data-points. For simplicity, we will pass in the same inputs we used for testing, however you could pass completely new arrays and see what predictions it produces. We can then display the results in the &lt;code&gt;preds_node&lt;/code&gt; reference node variable that we defined, which will show in the display.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gdscript&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... code from previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_ml&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; preds &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; kml.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;predict&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(xi, xj)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    preds_node.text &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(preds)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from latter blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally we want to also display the learned parameters, which in this case it includes &lt;code&gt;w1&lt;/code&gt; , &lt;code&gt;w2&lt;/code&gt; and the &lt;code&gt;bias&lt;/code&gt; . We are able to display the weights and bias in the respective labels.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gdscript&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# ... code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_ml&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get_params&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w1_node.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set_text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w2_node.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set_text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    bias_node.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set_text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # ... code from latter blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The final thing to set up is to connect the “Kompute Train &amp;#x26; Predict” button into the &lt;code&gt;compute_ml&lt;/code&gt; function, which can be done by setting up a signal that points to the function itself via the editor.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-09.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 10&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Setting up the Signal to the compute_ml method in our script (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once this is all set up, we can run the Game and trigger the training and prediction using the provided inputs. We can then see the learned parameters as well as the prediction outputs. It is also possible to see how the learned parameters change as we modify the inputs &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;xi&lt;/code&gt; and &lt;code&gt;xj&lt;/code&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-10.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 11&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Kompute ML Godot interface with resulting parameters (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;kompute-ml-implementation&quot;&gt;Kompute ML Implementation&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that there is an intuition on what is happening in the game level, we are able to code our underlying C++ class to create the Godot bindings using the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Kompute framework&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-11.jpg&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 12&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;em&gt;Kompute &lt;a href=&quot;https://ethicalml.github.io/vulkan-kompute/overview/reference.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Architecture Design&lt;/a&gt; (Image by Author)&lt;/em&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We will be following the design principles of Kompute which are outlined in this accompanying diagram showing the different components. We will be following this workflow to load the data in the GPU and perform the training.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;The header file for the Godot class binding implementation is outlined below, which we will break down in detail. As you can see creating a C++ class with bindings is quite intuitive, and you can see the same functions that we used to call from our Godot GdScript above.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;KomputeLogisticRegression.hpp Implementation&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#pragma&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; once&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#x3C;Godot.hpp&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#x3C;Node2D.hpp&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#x3C;Array.hpp&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;kompute/Kompute.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; godot&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeLogisticRegression&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Node2D&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;private:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    GODOT_CLASS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;KomputeLogisticRegression&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Node2D&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // For custom module use gdclass&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // GDCLASS(KomputeSummatorNode, Node);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;public:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    KomputeLogisticRegression&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; train&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xJ&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    Array&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; predict&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xJ&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    Array&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; get_params&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    static&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; _register_methods&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // For custom module use bind methods instead&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //static void _bind_methods();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;private:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor mWeights;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor mBias;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::string LR_SHADER &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; R&quot;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;//... rest of header file&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;The initial section of the class header file includes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;kompute/Kompute.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#x3C;Godot.hpp&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#x3C;Node2D.hpp&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#x3C;Array.hpp&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; godot&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; KomputeLogisticRegression&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Node2D&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;private:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    GODOT_CLASS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;KomputeLogisticRegression&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Node2D&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;Import of the &lt;code&gt;Kompute.hpp&lt;/code&gt;header containing all the Kompute dependencies that we’ll use in this project&lt;/li&gt;
&lt;li&gt;The top-level &lt;code&gt;Godot.hpp&lt;/code&gt; import is required to ensure all Godot components are available.&lt;/li&gt;
&lt;li&gt;Node2D is the resource that we will be inheriting from, but you can inherit from other classes in &lt;a href=&quot;https://docs.godotengine.org/en/stable/development/cpp/inheritance_class_tree.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the inheritance tree&lt;/a&gt; depending on how you plan to use your custom Godot class&lt;/li&gt;
&lt;li&gt;For data passing across the application, we will be using a Godot &lt;code&gt;Array&lt;/code&gt; which will handle transfer between GdScript and the Naive C++, as well as a Kompute &lt;code&gt;Tensor&lt;/code&gt; which will handle the GPU data management.&lt;/li&gt;
&lt;li&gt;The GODOT_CLASS macro definition extends the class by adding extra Godot related functionality. As we will see below, you will need to use GDCLASS instead when building as a Godot custom module.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;Following the base functionality, we have to define the core logic:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;public:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    KomputeLogisticRegression&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; train&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xJ&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    Array&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; predict&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xJ&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    Array&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; get_params&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;code&gt;void train(Array y, Array xI, Array xJ)&lt;/code&gt; —Trains the machine learning model using the GPU native code for the logistic regression model. It takes the input array(s) &lt;code&gt;X&lt;/code&gt;, and the array &lt;code&gt;y&lt;/code&gt;containing the expected outputs.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Array predict(Array xI, Array xJ)&lt;/code&gt; —Perform the inference request. In this implementation it is not using GPU code as generally there tends to be less performance gains through parallelization on the inference side. However there are still expected performance gains if multiple inputs are processed in parallel (which this function allows for).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Array get_params()&lt;/code&gt; —Returns an array containing the learned parameters in the format of &lt;code&gt;[ &amp;#x3C;weight_1&gt;, &amp;#x3C;weight_2&gt;, &amp;#x3C;bias&gt; ]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-reveal=&quot;&quot;&gt;We then are able to declare the methods that will be bound between the C++ and the high level GdScript Godot Engine, and accessible to the editor and broader Game in general. We’ll look briefly below at the code required to register a function.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... previous code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    static&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; _register_methods&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... latter code blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;For data management we will be using Kompute tensors as well as Arrays — in this case we will only need to “learn” and “persist” the weights and biases of our logistic regression model.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;private:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor mWeights;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    kp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::Tensor mBias;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... code from latter blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;Finally, we also define the shader code, which is basically &lt;a href=&quot;https://en.wikipedia.org/wiki/OpenGL_Shading_Language&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the code that will be executed as machine code inside of the GPU&lt;/a&gt;. Kompute allows us to pass a string containing the code, however for production deployments it is possible to convert the shaders to binary, and also use the utilities available to convert into header files.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-reveal=&quot;&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... code from previous blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::string LR_SHADER &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; R&quot;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    // ... shader code excluded for simplicity&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ... code from latter blocks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-reveal=&quot;&quot;&gt;If you are interested in the full implementation you can find all the files in the &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/godot_example/examples/godot_logistic_regression/gdnative_shared&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;gdnative implementation&lt;/a&gt; and &lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/godot_example/examples/godot_logistic_regression/custom_module&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;custom module&lt;/a&gt; implementation folders. Furthermore if you are interested in the theoretical and underlying foundational concepts of these techniques, this is covered fully in &lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a#6c88&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;our previous post&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;compiling-and-integrating-into-godot&quot;&gt;Compiling and Integrating into Godot&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Now that we have the base code for our GPU optimized machine learning model, we are now able to proceed to running it in our Godot game engine. There are two main ways in which Godot allows us to add C++ code into our projects:&lt;/p&gt;
&lt;ol data-reveal=&quot;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/godot_example/examples/godot_logistic_regression/gdnative_shared&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;GdNative Library Build Instructions&lt;/strong&gt;&lt;/a&gt;— In Godot you can add your own “GdNative scripts” which are basically C++ classes with bindings to GdScript, which means these can be used and referenced dynamically in the project. This approach works with the standard Godot installation and doesn’t require re-compiling the full editor like the 2nd option.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/godot_example/examples/godot_logistic_regression/custom_module&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Custom Module&lt;/strong&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/EthicalML/vulkan-kompute/tree/godot_example/examples/godot_logistic_regression/gdnative_shared&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;strong&gt;Build Instructions&lt;/strong&gt;&lt;/a&gt;— In Godot only the underlying core classes are part of the “core” components; everything else — the UI, the editor, the GdScript language, the networking capabilities — are custom models. Writing a custom module is easy, and this is how we are able to expose some of the core Kompute functionality. This option requires the &lt;strong&gt;full Godot C++ project to be recompiled&lt;/strong&gt; with the custom module.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-reveal=&quot;&quot;&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;#x22;src&amp;#x22;:&amp;#x22;./image-12.png&amp;#x22;,&amp;#x22;alt&amp;#x22;:&amp;#x22;Image 13&amp;#x22;,&amp;#x22;index&amp;#x22;:0}&quot;&gt;&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;Once you set one of these methods through the instructions, you will be able to access the custom object from within Godot. There are some nuanced implementation differences between each approach.&lt;/p&gt;
&lt;p data-reveal=&quot;&quot;&gt;We won’t be covering specific build details in the blog post, but you will be able to find the exact code and build instructions in the GdNative Library / Custom Module links above.&lt;/p&gt;
&lt;/section&gt;&lt;section class=&quot;article-section blog-section&quot;&gt;&lt;h2 data-reveal=&quot;&quot; id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;
&lt;p data-reveal=&quot;&quot;&gt;Congratulations, you’ve made it all the way to the end! Although there was a broad range of topics covered in this post, there is a massive amount of concepts that were skimmed through. These include the underlying Vulkan concepts, GPU computing fundamentals, machine learning best practices, and more advanced Kompute concepts. Luckily, there are resources online to expand your knowledge on each of these. Here are some links I recommend for further reading:&lt;/p&gt;
&lt;ul data-reveal=&quot;&quot;&gt;
&lt;li&gt;“&lt;a href=&quot;https://towardsdatascience.com/machine-learning-and-data-processing-in-the-gpu-with-vulkan-kompute-c9350e5e5d3a&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Machine Learning in Mobile &amp;#x26; Cross-Vendor GPUs Made Simple With Kompute &amp;#x26; Vulkan&lt;/a&gt;” article with a deeper dive in theory and concepts&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://axsaucedo.github.io/vulkan-kompute/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kompute Documentation&lt;/a&gt; for more details and further examples&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ethical.institute/mle.html&quot;&gt;The Machine Learning Engineer Newsletter&lt;/a&gt; if you want to keep updated on articles around Machine Learning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EthicalML/awesome-production-machine-learning/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Awesome Production Machine Learning&lt;/a&gt; list for open source tools to deploy, monitor, version and scale your machine learning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fast.ai/2018/09/26/ml-launch/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Introduction to ML for Coders course&lt;/a&gt; by FastAI to learn further machine learning concepts&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vulkan-tutorial.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Vulkan SDK Tutorial&lt;/a&gt; for a deep dive into the underlying Vulkan components&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded><category>gpu</category><category>kompute</category><category>machine-learning</category><category>game-development</category></item></channel></rss>