[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"navigation":3,"url-settings":86,"blog-\u002Fblog\u002Frunning-a-jax-program-from-dart-using-c-ffi":671,"blog-author-\u002Fblog\u002Frunning-a-jax-program-from-dart-using-c-ffi":1070,"i-material-symbols:arrow-back-rounded":1090},{"id":4,"extension":5,"footer":6,"header":73,"meta":83,"stem":84,"__hash__":85},"navigation\u002Fdata\u002Fshared\u002Fnavigation.yml","yml",{"brand":7,"columns":13,"legal":63},{"name":8,"tagline":9,"downloadCta":10},"Pieces","The memory layer for modern work.",{"label":11,"href":12},"All downloads","\u002Fdownloads",[14,26,39,51],{"title":15,"links":16},"Product",[17,20,23],{"label":18,"href":19},"Pieces Desktop","\u002F",{"label":21,"href":22},"Pieces Enterprise","\u002Fenterprise",{"label":24,"href":25},"Pieces MCP","\u002Fmcp",{"title":27,"links":28},"Resources",[29,33,36],{"label":30,"href":31,"external":32},"Documentation","url:docs.home",true,{"label":34,"href":35},"Blog","\u002Fblog",{"label":37,"href":38,"external":32},"GitHub","url:github.org",{"title":40,"links":41},"Community",[42,45,48],{"label":43,"href":44,"external":32},"Discord","url:social.discord",{"label":46,"href":47,"external":32},"X \u002F Twitter","url:social.x",{"label":49,"href":50,"external":32},"LinkedIn","url:social.linkedin",{"title":52,"links":53},"Company",[54,57,60],{"label":55,"href":56},"About","\u002Fabout",{"label":58,"href":59},"Updates","\u002Fupdates",{"label":61,"href":62},"Contact","\u002Fcontact",[64,67,70],{"label":65,"href":66},"Privacy Policy","\u002Flegal\u002Fprivacy",{"label":68,"href":69},"Refund Policy","\u002Flegal\u002Frefund",{"label":71,"href":72},"Terms of Service","\u002Flegal\u002Fterms",{"links":74,"signIn":75,"contact":78,"cta":80},[],{"label":76,"href":77},"Manage account","url:portal.home",{"label":79,"href":62},"Get in touch",{"label":81,"href":82},"Download","url:routes.downloads",{},"data\u002Fshared\u002Fnavigation","XlSALC7vYCXHcmcXnjJViwIZKsqnQWF4bn4o9RrcSBE",{"id":87,"extension":5,"links":88,"meta":668,"stem":669,"__hash__":670},"urlSettings\u002Fdata\u002Fshared\u002Furls.yml",[89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,292,296,300,303,307,311,314,318,322,326,330,334,338,342,346,350,354,358,362,366,370,374,378,382,386,390,394,398,402,406,410,414,418,422,426,430,434,438,442,446,450,454,458,461,465,469,473,477,481,485,488,491,494,497,501,505,508,512,516,520,524,528,532,536,540,544,548,552,556,559,563,567,571,575,579,582,585,588,592,595,599,603,607,611,614,618,622,625,628,631,635,639,643,646,649,652,656,660,664],{"key":90,"label":91,"href":92},"downloads.desktop","Desktop download page","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdownload",{"key":94,"label":95,"href":96},"downloads.macOS.dmgArm64","macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg-arm64\u002Fdownload",{"key":98,"label":99,"href":100},"downloads.macOS.dmgIntel","macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg\u002Fdownload",{"key":102,"label":103,"href":104},"downloads.macOS.pkg","macOS PKG","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg\u002Fdownload",{"key":106,"label":107,"href":108},"downloads.macOS.universal","Desktop macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fmacos-universal\u002Fdownload",{"key":110,"label":111,"href":112},"downloads.macOS.pkgArm64","Desktop macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd-arm64\u002Fdownload",{"key":114,"label":115,"href":116},"downloads.macOS.pkgIntel","Desktop macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd\u002Fdownload",{"key":118,"label":119,"href":120},"downloads.windows.appinstaller","Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fpieces_for_x.appinstaller",{"key":122,"label":123,"href":124},"downloads.windows.exe","Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-exe\u002Fdownload",{"key":126,"label":127,"href":128},"downloads.windows.msix","Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-msix\u002Fdownload",{"key":130,"label":131,"href":132},"downloads.windows.suiteManager","Windows Suite Manager","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_suite_windows\u002Fappinstaller\u002Fdownload",{"key":134,"label":135,"href":136},"downloads.linux.flatpakRepo","Linux Flatpak repository","https:\u002F\u002Fbuilds.pieces.app\u002Fpieces-flatpak-repo\u002Fpieces-flatpak.flatpakrepo",{"key":138,"label":139,"href":140},"downloads.linux.snapDesktop","Linux Snap Desktop","https:\u002F\u002Fsnapcraft.io\u002Fpieces-for-developers",{"key":142,"label":143,"href":144},"downloads.linux.snapPiecesOS","Linux Snap PiecesOS","https:\u002F\u002Fsnapcraft.io\u002Fpieces-os",{"key":146,"label":147,"href":148},"downloads.linux.snap","Desktop Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fsnap\u002Fdownload",{"key":150,"label":151,"href":152},"downloads.piecesOS.macOS.dmgArm64","PiecesOS macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg-arm64\u002Fdownload",{"key":154,"label":155,"href":156},"downloads.piecesOS.macOS.dmgIntel","PiecesOS macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg\u002Fdownload",{"key":158,"label":159,"href":160},"downloads.piecesOS.macOS.universal","PiecesOS macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fmacos-universal\u002Fdownload",{"key":162,"label":163,"href":164},"downloads.piecesOS.macOS.pkgArm64","PiecesOS macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only-arm64\u002Fdownload",{"key":166,"label":167,"href":168},"downloads.piecesOS.macOS.pkgIntel","PiecesOS macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only\u002Fdownload",{"key":170,"label":171,"href":172},"downloads.piecesOS.windows.appinstaller","PiecesOS Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fos_server.appinstaller",{"key":174,"label":175,"href":176},"downloads.piecesOS.windows.exe","PiecesOS Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-exe\u002Fdownload",{"key":178,"label":179,"href":180},"downloads.piecesOS.windows.msix","PiecesOS Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-msix\u002Fdownload",{"key":182,"label":183,"href":184},"downloads.piecesOS.linux.snap","PiecesOS Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fsnap\u002Fdownload",{"key":186,"label":187,"href":188},"downloads.combined.macOS.appleSilicon","Combined macOS installer Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-arm64\u002Fdownload",{"key":190,"label":191,"href":104},"downloads.combined.macOS.intel","Combined macOS installer Intel",{"key":193,"label":194,"href":195},"downloads.guides.macOS","macOS installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fmacos-installation-guide",{"key":197,"label":198,"href":199},"downloads.guides.windows","Windows installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fwindows-installation-guide",{"key":201,"label":202,"href":203},"downloads.guides.linux","Linux installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide",{"key":205,"label":206,"href":207},"downloads.guides.linuxFlatpak","Linux Flatpak installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide\u002Fflatpak",{"key":209,"label":210,"href":211},"downloads.guides.linuxSnap","Linux Snap installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide\u002Fsnap",{"key":213,"label":214,"href":215},"downloads.guides.piecesOS","PiecesOS manual installation","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fmanual-installation",{"key":217,"label":218,"href":219},"extensions.chrome","Chrome extension","https:\u002F\u002Fchrome.google.com\u002Fwebstore\u002Fdetail\u002Fpieces-save-code-snippets\u002Figbgibhbfonhmjlechmeefimncpekepm",{"key":221,"label":222,"href":223},"extensions.firefox","Firefox add-on","https:\u002F\u002Faddons.mozilla.org\u002Fen-US\u002Ffirefox\u002Faddon\u002Fpieces-save-code-from-the-web\u002F",{"key":225,"label":226,"href":227},"extensions.edge","Edge add-on","https:\u002F\u002Fmicrosoftedge.microsoft.com\u002Faddons\u002Fdetail\u002Fpieces-save-code-snippet\u002Fhglfimcdgonaeeobjckfdabcldfidmim",{"key":229,"label":230,"href":231},"extensions.vscode","VS Code extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.pieces-vscode",{"key":233,"label":234,"href":235},"extensions.visualStudio","Visual Studio extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.PiecesVisualStudio",{"key":237,"label":238,"href":239},"extensions.jetbrains","JetBrains plugin","https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F17328-pieces--save-search-share--reuse-code-snippets",{"key":241,"label":242,"href":243},"extensions.obsidian","Obsidian plugin","https:\u002F\u002Fobsidian.md\u002Fplugins?id=pieces-for-developers",{"key":245,"label":246,"href":247},"extensions.sublime","Sublime package","https:\u002F\u002Fpackagecontrol.io\u002Fpackages\u002FPieces",{"key":249,"label":250,"href":251},"extensions.neovim","Neovim plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neo_vim",{"key":253,"label":254,"href":255},"extensions.jupyterlab","JupyterLab plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fjupyterlab-pieces",{"key":257,"label":258,"href":259},"extensions.cli","Pieces CLI","https:\u002F\u002Fpypi.org\u002Fproject\u002Fpieces-cli\u002F",{"key":261,"label":262,"href":263},"docs.home","Documentation home","https:\u002F\u002Fdocs.pieces.app",{"key":265,"label":266,"href":267},"docs.getStarted","Get started docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces",{"key":269,"label":270,"href":271},"docs.api","API docs","https:\u002F\u002Fdocs.pieces.app\u002Fapi",{"key":273,"label":274,"href":275},"docs.desktop.overview","Desktop overview","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop",{"key":277,"label":278,"href":279},"docs.desktop.onboarding","Desktop onboarding","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fonboarding",{"key":281,"label":282,"href":283},"docs.desktop.timeline","Desktop timeline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Ftimeline",{"key":285,"label":286,"href":287},"docs.desktop.summaries","Desktop summaries docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fsingle-click-summaries",{"key":289,"label":290,"href":291},"docs.desktop.search","Desktop conversational search docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconversational-search",{"key":293,"label":294,"href":295},"docs.desktop.drive","Desktop drive docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdrive",{"key":297,"label":298,"href":299},"docs.desktop.account","Desktop account settings docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconfiguration\u002Faccount",{"key":301,"label":302,"href":92},"docs.desktop.download","Desktop download docs",{"key":304,"label":305,"href":306},"docs.piecesOS.overview","PiecesOS overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies",{"key":308,"label":309,"href":310},"docs.piecesOS.details","PiecesOS details docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os",{"key":312,"label":313,"href":215},"docs.piecesOS.install","PiecesOS install docs",{"key":315,"label":316,"href":317},"docs.piecesOS.quickMenu","PiecesOS quick menu docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fquick-menu",{"key":319,"label":320,"href":321},"docs.piecesOS.storage","On-device storage docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fon-device-storage",{"key":323,"label":324,"href":325},"docs.piecesOS.troubleshooting","PiecesOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Ftroubleshooting",{"key":327,"label":328,"href":329},"docs.mcp.overview","MCP overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp",{"key":331,"label":332,"href":333},"docs.mcp.cursor","MCP Cursor docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcursor",{"key":335,"label":336,"href":337},"docs.mcp.vscode","MCP VS Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fvs-code",{"key":339,"label":340,"href":341},"docs.mcp.claudeDesktop","MCP Claude Desktop docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-desktop",{"key":343,"label":344,"href":345},"docs.mcp.claudeCode","MCP Claude Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-code",{"key":347,"label":348,"href":349},"docs.mcp.claudeCowork","MCP Claude Cowork docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-cowork",{"key":351,"label":352,"href":353},"docs.mcp.githubCopilot","MCP GitHub Copilot docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgithub-copilot",{"key":355,"label":356,"href":357},"docs.mcp.goose","MCP Goose docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoose",{"key":359,"label":360,"href":361},"docs.mcp.windsurf","MCP Windsurf docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fwindsurf",{"key":363,"label":364,"href":365},"docs.mcp.zed","MCP Zed docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fzed",{"key":367,"label":368,"href":369},"docs.mcp.jetbrains","MCP JetBrains docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fjetbrains-ides",{"key":371,"label":372,"href":373},"docs.mcp.continueDev","MCP Continue docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcontinue-dev",{"key":375,"label":376,"href":377},"docs.mcp.cline","MCP Cline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcline",{"key":379,"label":380,"href":381},"docs.mcp.raycast","MCP Raycast docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fraycast",{"key":383,"label":384,"href":385},"docs.mcp.rovoDevCli","MCP Rovo Dev CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Frovo-dev-cli",{"key":387,"label":388,"href":389},"docs.mcp.openaiCodexCli","MCP OpenAI Codex CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenai-codex-cli",{"key":391,"label":392,"href":393},"docs.mcp.googleGeminiCli","MCP Google Gemini CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoogle-gemini-cli",{"key":395,"label":396,"href":397},"docs.mcp.amazonQ","MCP Amazon Q docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Famazon-q-developer",{"key":399,"label":400,"href":401},"docs.mcp.chatgptDev","MCP ChatGPT Developer Mode docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fchatgpt-developer-mode",{"key":403,"label":404,"href":405},"docs.mcp.openclaw","MCP OpenClaw docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenclaw",{"key":407,"label":408,"href":409},"docs.mcp.mcpRemote","MCP Remote docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fmcp-remote",{"key":411,"label":412,"href":413},"docs.mcp.ngrok","MCP ngrok docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fngrok-setup",{"key":415,"label":416,"href":417},"docs.troubleshooting.macOS","macOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fmacos",{"key":419,"label":420,"href":421},"docs.troubleshooting.windows","Windows troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fwindows",{"key":423,"label":424,"href":425},"docs.troubleshooting.linux","Linux troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Flinux",{"key":427,"label":428,"href":429},"docs.privacy","Privacy and security docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fprivacy-security-your-data",{"key":431,"label":432,"href":433},"docs.support","Support docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fsupport",{"key":435,"label":436,"href":437},"portal.home","Pieces portal","https:\u002F\u002Fportal.pieces.app",{"key":439,"label":440,"href":441},"site.home","Website home","https:\u002F\u002Fpieces.app",{"key":443,"label":444,"href":445},"site.about","About page","https:\u002F\u002Fpieces.app\u002Fabout",{"key":447,"label":448,"href":449},"site.features","Features page","https:\u002F\u002Fpieces.app\u002Ffeatures",{"key":451,"label":452,"href":453},"site.plugins","Plugins page","https:\u002F\u002Fpieces.app\u002Fplugins",{"key":455,"label":456,"href":457},"site.contact","Contact page","https:\u002F\u002Fpieces.app\u002Fcontact",{"key":459,"label":58,"href":460},"site.updates","https:\u002F\u002Fpieces.app\u002Fupdates",{"key":462,"label":463,"href":464},"site.news","News","https:\u002F\u002Fpieces.app\u002Fnews",{"key":466,"label":467,"href":468},"site.events","Community events","https:\u002F\u002Fpieces.app\u002Fcommunity\u002Fevents",{"key":470,"label":471,"href":472},"site.userStories","User stories","https:\u002F\u002Fpieces.app\u002Fuser-stories",{"key":474,"label":475,"href":476},"site.academy","Academy","https:\u002F\u002Fpieces.app\u002Flearn\u002Facademy",{"key":478,"label":479,"href":480},"site.support","Website support","https:\u002F\u002Fpieces.app\u002Fsupport",{"key":482,"label":483,"href":484},"site.standup","Standup","https:\u002F\u002Fpieces.app\u002Fstandup",{"key":486,"label":34,"href":487},"site.blog","https:\u002F\u002Fcode.pieces.app\u002Fblog",{"key":489,"label":43,"href":490},"social.discord","https:\u002F\u002Fdiscord.gg\u002Fgetpieces",{"key":492,"label":46,"href":493},"social.x","https:\u002F\u002Fx.com\u002Fgetpieces",{"key":495,"label":496,"href":493},"social.twitter","Twitter",{"key":498,"label":499,"href":500},"social.instagram","Instagram","https:\u002F\u002Fwww.instagram.com\u002Fgetpieces\u002F",{"key":502,"label":503,"href":504},"social.tiktok","TikTok","https:\u002F\u002Fwww.tiktok.com\u002F@getpieces",{"key":506,"label":49,"href":507},"social.linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fgetpieces\u002F",{"key":509,"label":510,"href":511},"social.youtube","YouTube","https:\u002F\u002Fyoutube.com\u002F@getpieces",{"key":513,"label":514,"href":515},"github.org","GitHub organization","https:\u002F\u002Fgithub.com\u002Fpieces-app",{"key":517,"label":518,"href":519},"github.support","GitHub support","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport",{"key":521,"label":522,"href":523},"github.issues","GitHub issues","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fissues",{"key":525,"label":526,"href":527},"github.discussions","GitHub discussions","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fdiscussions",{"key":529,"label":530,"href":531},"github.documentation","GitHub documentation","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fdocumentation",{"key":533,"label":534,"href":535},"github.opensource","GitHub open source","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fopensource",{"key":537,"label":538,"href":539},"github.sdks.python","Python SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-python",{"key":541,"label":542,"href":543},"github.sdks.typescript","TypeScript SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-typescript",{"key":545,"label":546,"href":547},"github.sdks.dart","Dart SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-dart",{"key":549,"label":550,"href":551},"github.sdks.kotlin","Kotlin SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-kotlin",{"key":553,"label":554,"href":555},"github.plugins.obsidian","Obsidian plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fobsidian-pieces",{"key":557,"label":558,"href":255},"github.plugins.jupyterlab","JupyterLab plugin repository",{"key":560,"label":561,"href":562},"github.plugins.sublime","Sublime plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_sublime",{"key":564,"label":565,"href":566},"github.plugins.neovim","Neovim plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neovim",{"key":568,"label":569,"href":570},"github.cliAgent","CLI agent repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fcli-agent",{"key":572,"label":573,"href":574},"github.mcpDart","MCP Dart repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fmcp_dart",{"key":576,"label":577,"href":578},"github.awesomePieces","Awesome Pieces repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fawesome-pieces",{"key":580,"label":581,"href":66},"legal.privacyPolicy","Privacy policy",{"key":583,"label":584,"href":69},"legal.refundPolicy","Refund policy",{"key":586,"label":587,"href":72},"legal.terms","Terms",{"key":589,"label":590,"href":591},"legal.security","Legal security","https:\u002F\u002Fpieces.app\u002Flegal\u002Fsecurity",{"key":593,"label":594,"href":511},"videos.youtubeChannel","YouTube channel",{"key":596,"label":597,"href":598},"videos.gettingStartedDesktop","Getting started desktop video","https:\u002F\u002Fyoutu.be\u002FdUr1lRM_TYk",{"key":600,"label":601,"href":602},"videos.snippetDiscoveryxR","Snippet discovery video","https:\u002F\u002Fyoutu.be\u002FG6vb1USw-30",{"key":604,"label":605,"href":606},"sales.bookACall","Book a sales call","https:\u002F\u002Fcalendar.app.google\u002FWVUDtUfNy5Vst3sH7",{"key":608,"label":609,"href":610},"sales.enterprise","Enterprise form","https:\u002F\u002Fgetpieces.typeform.com\u002Fto\u002FaVQFTvpE",{"key":612,"label":613,"href":527},"sales.feedback","Feedback discussions",{"key":615,"label":616,"href":617},"sales.earlyAccess","Early access form","https:\u002F\u002Fgetpieces.typeform.com\u002Fearlyaccess",{"key":619,"label":620,"href":621},"sales.supportEmail","Support email","mailto:support@pieces.app",{"key":623,"label":624,"href":19},"routes.home","Home route",{"key":626,"label":627,"href":56},"routes.about","About route",{"key":629,"label":630,"href":12},"routes.downloads","Downloads route",{"key":632,"label":633,"href":634},"routes.thanks","Post-install thanks route","\u002Finstall\u002Fthanks",{"key":636,"label":637,"href":638},"routes.pricing","Pricing route","\u002Fpricing",{"key":640,"label":641,"href":642},"cta.freeTrial","Start free trial CTA (Pieces Pro) — used by \u002Fcampaigns\u002F* landing pages","https:\u002F\u002Fcampaigns.pieces.app\u002F",{"key":644,"label":645,"href":22},"routes.enterprise","Enterprise route",{"key":647,"label":648,"href":62},"routes.contact","Contact route",{"key":650,"label":651,"href":59},"routes.updates","Updates route",{"key":653,"label":654,"href":655},"routes.migrationError","Migration error route","\u002Fmigration\u002Ferror",{"key":657,"label":658,"href":659},"routes.authenticated","Post-login authenticated route","\u002Fauth\u002Fsigned-in",{"key":661,"label":662,"href":663},"routes.signed-out","Signed out route","\u002Fauth\u002Fsigned-out",{"key":665,"label":666,"href":667},"routes.authentication-error","Authentication error route","\u002Fauth\u002Ferror",{},"data\u002Fshared\u002Furls","2AvfSWI6bZACH5Kr1ZS3txMLjteRjCjbDR_ul1uRZ9Q",{"id":672,"title":673,"author":674,"authorPhoto":675,"authorPhotoAlt":676,"authorSlug":677,"body":678,"buttonText":676,"buttonUrl":676,"category":1059,"date":1060,"description":1061,"draft":1062,"editorsPick":1062,"extension":1063,"featured":1062,"image":1064,"imageAlt":676,"meta":1065,"navigation":32,"ogImage":676,"ogImageAlt":676,"path":1066,"seo":1067,"stem":1068,"tags":676,"__hash__":1069},"blog\u002Fblog\u002Frunning-a-jax-program-from-dart-using-c-ffi.md","Running a JAX program from Dart using C++ FFI","Dominik Huss","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Frunning-a-jax-program-from-dart-using-c-ffi\u002Fauthor.jpg",null,"dominik-huss",{"type":679,"value":680,"toc":1046},"minimark",[681,686,690,693,703,706,709,712,715,718,722,731,734,737,740,743,754,760,763,769,775,778,781,787,790,793,796,799,801,805,808,811,814,818,821,824,830,838,845,848,861,864,876,885,891,894,897,903,907,910,917,923,926,932,938,944,953,956,962,969,972,976,979,986,992,1003,1008,1014,1021,1027,1030,1034,1037,1040,1043],[682,683,685],"h2",{"id":684},"building-machine-learning-enabled-applications","Building machine learning-enabled applications",[687,688,689],"p",{},"When choosing the programming language and main frameworks for building your application one usually focuses on factors such as performance, development ease, or the ability to deploy across different operating systems and devices. The most popular and renowned of them tend to have most of the desired properties or propose attractive tradeoffs between them.",[687,691,692],{},"For example, writing your application purely in C++ might make it run faster, but is going to slow down development at the same time.",[687,694,695,702],{},[696,697,701],"a",{"href":698,"rel":699},"https:\u002F\u002Fpieces.app\u002Fblog\u002Fusing-pieces-flutter-to-build-pieces",[700],"nofollow","Dart with Flutter"," on the other hand is slower, but offers solid initial abstraction of aspects of memory management as well as has great support for building local applications across different operating systems.",[687,704,705],{},"One thing that most well-established frameworks are missing is robust native support for machine learning (ML) downstream tasks. This is not particularly surprising, since they’ve all been designed before the recent AI surge, but it poses a difficult question for the ecosystem. How do we integrate the ML stack into the application efficiently?",[687,707,708],{},"There are currently some ways of achieving this, although none of them is without drawbacks. If the application is deployed locally one of the most popular tools used to run an ML model within it is ONNX Runtime. Having a universal serialization-deserialization scheme it enables ML Engineers to export their models written in popular ML frameworks to a format that then can be loaded into the runtime and called from the developed application.",[687,710,711],{},"However, one of the downsides of ONNX Runtime is that the produced code representation doesn’t get optimized to the extent that it could, especially when running on a CPU.",[687,713,714],{},"Additionally, what if we’d also like to include some more generalized algorithms written by our Data Scientists that do not conform to the standard deep learning model archetype? That is going to be quite cumbersome to achieve using this tool.",[687,716,717],{},"In this blog, we’ll be looking at the JAX library for Python that can aid us with resolving those problems. It enables the team to write heavily optimized code in Python that can express any general algorithms that can be written in pure Python and NumPy.",[682,719,721],{"id":720},"what-is-jax","What is JAX?",[687,723,724,725,730],{},"JAX is a Python library very similar to NumPy that’s been getting more and more popular amongst machine learning practitioners over the past couple of years. Developed by Google it enables programmers to write ",[696,726,729],{"href":727,"rel":728},"https:\u002F\u002Fpieces.app\u002Fblog\u002Fwhy-llm-agnostic-solutions-are-the-future-of-dev-tools",[700],"platform-agnostic code"," that can be run on CPUs, GPUs, and TPUs without any additional effort. Additionally, JAX has a built-in autograd, JIT, and parallelization support to enable efficient implementation of any SOTA (state-of-the-art) machine learning models and algorithms.",[687,732,733],{},"JAX code can be executed particularly fast thanks to utilizing an XLA compiler after tracing and translating the user-written program to StableHLO.",[687,735,736],{},"Ultimately JAX can be seen as a way to give a lot of control to the programmer over how exactly the model is run, which the other popular (deep) machine learning frameworks like PyTorch don’t give by being a lot more “low-level”.",[687,738,739],{},"Combined with being way more accessible to the average ML scientist (after all, it’s “just” supercharged NumPy) it has become very easy to speed up the training and inference time of machine learning models using JAX.",[687,741,742],{},"To illustrate this, below are two functions using NumPy and JAX respectively performing a simple value assignment to a vector.",[744,745,750],"pre",{"className":746,"code":748,"language":749},[747],"language-text","import numpy as np \n\ndef assign_numpy(): \n  a = np.empty(1000000) \n  a[:] = 1 \n  return a\n","text",[751,752,748],"code",{"__ignoreMap":753},"",[744,755,758],{"className":756,"code":757,"language":749},[747],"import jax.numpy as jnp \nimport jax\n\n@jax.jit \ndef assign_jax(): \n  a = jnp.empty(1000000) \n  return a.at[:].set(1)\n",[751,759,757],{"__ignoreMap":753},[687,761,762],{},"Using a Google Colab environment we can evaluate the execution speed of these two functions like so:",[744,764,767],{"className":765,"code":766,"language":749},[747],"%timeit assign_numpy()\n",[751,768,766],{"__ignoreMap":753},[744,770,773],{"className":771,"code":772,"language":749},[747],"%timeit assign_jax().block_until_ready()\n",[751,774,772],{"__ignoreMap":753},[687,776,777],{},"Note that we will use .block_until_ready() when running the code on a GPU\u002FTPU to enforce that we await the results from the accelerator for fair speed comparison.",[687,779,780],{},"On different platforms, we get:",[687,782,783],{},[784,785],"img",{"alt":753,"src":786},"https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Frunning-a-jax-program-from-dart-using-c-ffi\u002Fimg-001.png",[687,788,789],{},"It is important to note, that no changes to the code needed to be made for it to be run on these different platforms. This is not the case for common deep learning frameworks which will require the programmer to manually move the model and data onto a device.",[687,791,792],{},"We can observe that even for a single simple operation JAX shows to be faster when run on a CPU and a GPU.",[687,794,795],{},"Notably, the average execution time on the GPU and TPU includes moving data to and from the accelerator, which substantially contributes to the overall time performance. In non-trivial settings, where the executed program is longer the speed-up can be even more noticeable.",[687,797,798],{},"If we look at the TPU time we see that the over-the-wire cost dwarfs anything else - the takeaway here is that it only becomes useful to use a TPU when the model is sufficiently large in the first place.",[682,800],{"id":753},[682,802,804],{"id":803},"incorporating-jax-code-into-the-prod","Incorporating JAX code into the prod",[687,806,807],{},"We’ve established that using JAX can significantly speed up our training and inference time. How could we utilize this in a real-world application?",[687,809,810],{},"One way would be to create a containerized microservice that’s running a Python interpreter that can execute our code. That’s all well and good, and certainly a valid option for applications that are utilizing cloud-hosted computing.",[687,812,813],{},"But what if we needed to include and ship our algorithms in a locally run application? It is usually not common practice to deploy a Python interpreter within a product. To this end, we can make use of the fact that JAX compiles down with XLA which is a common backend available in other programming languages as well. The plan is to write our code comfortably in Python using JAX and then deploy and run it from within a compiled C++ library that can be easily incorporated into any project.",[682,815,817],{"id":816},"how-to-generate-an-hlo-proto-for-xla","How to generate an HLO proto for XLA",[687,819,820],{},"The first thing we’ll need to do (after writing our algorithm in Python using JAX naturally) is generate a specification of our JAX program that can be used as an input to an XLA compiler. Importantly we should make sure that our top-level JAX function that we’ll be calling can be transformed with jax.jit or any other transformation that forces a compilation like jax.pmap.",[687,822,823],{},"This is the example code we’ll be using for this demonstration.",[744,825,828],{"className":826,"code":827,"language":749},[747],"import jax.numpy as jnp \n\ndef fn(x, y, z): \n  return jnp.dot(x, y) \u002F z\n",[751,829,827],{"__ignoreMap":753},[687,831,832,833],{},"Make sure that the code is accessible as a ",[696,834,837],{"href":835,"rel":836},"https:\u002F\u002Fdocs.pieces.app\u002Fbuild\u002Fsdks\u002Fpython\u002F",[700],"package from Python.",[687,839,840,841,844],{},"For this I have put it in a file called prog.py, created a simple library called jax_example for myself, and installed it, such that I can now import it with ",[751,842,843],{},"from jax\\_example.prog import fn",". Information on how to do this can be found online, as we will not be going over creating Python libraries in this blog.",[687,846,847],{},"Normally when we’re just running everything from a Python script what happens is that:",[849,850,851,855,858],"ul",{},[852,853,854],"li",{},"Whenever the compilation is triggered, either manually ahead-of-time by calling .lower() on our transformed code, or just-in-time by just simply running any data through it, i.e. calling the function - the function is traced and an optimized specification is produced. Note that at this stage the shapes and types of the function arguments are getting baked in.",[852,856,857],{},"The specification is used to compile a program using XLA for a given platform. Whenever we rerun our code later this gets reused.",[852,859,860],{},"The compiled code gets called and we get the results back. Perhaps slightly confusingly print statements in our original code do not persist in the trace and therefore they are not present in the compiled version of the code. This means we’ll not be able to see any prints from our code after the initial one-time tracing.",[687,862,863],{},"What we’re doing here will split this process across the different parts of our flow:",[865,866,867,870,873],"ol",{},[852,868,869],{},"Staging out the specialization is going to happen once ahead of time during development. The resulting trace will become an asset that gets shipped with the application.",[852,871,872],{},"The compilation happens on the target device just-in-time in the lifecycle of the application process itself. This could theoretically be done ahead-of-time if we knew the exact specification of the target machine which is not realistic in this scenario. This will be handled by the C++ library.",[852,874,875],{},"The compiled code run within the C++ library gets called through an FFI from Dart.",[687,877,878,879,884],{},"To achieve the first goal, namely creating the specification, we can use a tool script provided by JAX itself. We can clone the official ",[696,880,883],{"href":881,"rel":882},"https:\u002F\u002Fgithub.com\u002Fjax-ml\u002Fjax",[700],"JAX repository"," and inspect jax\u002Ftools\u002Fjax_to_ir.py. We will need to run:",[744,886,889],{"className":887,"code":888,"language":749},[747]," python jax_to_ir.py --fn jax_example.prog.fn --input_shapes '[(\"x\", \"f32[2,2]\"), (\"y\", \"f32[2,2]\")]' --constants '{\"z\": 2.0}' --ir_format HLO --ir_human_dest \u002Ftmp\u002Ffn_hlo.txt --ir_dest \u002Ftmp\u002Ffn_hlo.pb\n",[751,890,888],{"__ignoreMap":753},[687,892,893],{},"This will create the code specification files. For simplicity’s sake, we’ve put them in a globally accessible path.",[687,895,896],{},"Ideally, those files would be placed in the application’s assets folder, as we’ll need to ship them with it. We can inspect the fn_hlo.txt file:",[744,898,901],{"className":899,"code":900,"language":749},[747],"HloModule xla_computation_ordered_wrapper, entry_computation_layout={(f32[2,2]{1,0}, f32[2,2]{1,0})->(f32[2,2]{1,0})}\n\nENTRY main.8 {\n  Arg_0.1 = f32[2,2]{1,0} parameter(0)\n  Arg_1.2 = f32[2,2]{1,0} parameter(1)\n  dot.5 = f32[2,2]{1,0} dot(Arg_0.1, Arg_1.2), lhs_contracting_dims={1}, rhs_contracting_dims={0}\n  constant.3 = f32[] constant(2)\n  broadcast.4 = f32[2,2]{1,0} broadcast(constant.3), dimensions={}\n  divide.6 = f32[2,2]{1,0} divide(dot.5, broadcast.4)\n  ROOT tuple.7 = (f32[2,2]{1,0}) tuple(divide.6)\n}\n",[751,902,900],{"__ignoreMap":753},[682,904,906],{"id":905},"creating-a-c-dylib-that-uses-tensorflow-xla-backend","Creating a C++ dylib that uses TensorFlow XLA backend",[687,908,909],{},"We will now create a C++ dylib that will use the files generated earlier and compile them with XLA. For this we can continue to utilize the JAX repository we’ve cloned earlier. We will want to head over to jax\u002Fexamples\u002Fjax_cpp and make a few modifications.",[687,911,912,913,916],{},"We will want to add a header file called ",[751,914,915],{},"main.h",":",[744,918,921],{"className":919,"code":920,"language":749},[747],"#ifndef MAIN_H \n#define MAIN_H \n\n#ifdef __cplusplus \nextern \"C\" { \n#endif \n\nint bar(int foo); \n\n#ifdef __cplusplus \n} \n#endif \n\n#endif  \u002F\u002F MAIN_H\n",[751,922,920],{"__ignoreMap":753},[687,924,925],{},"Next we will want to modify the BUILD file such that it builds a dynamic library for us:",[744,927,930],{"className":928,"code":929,"language":749},[747],"# Copyright 2021 The JAX Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https:\u002F\u002Fwww.apache.org\u002Flicenses\u002FLICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# package(default_applicable_licenses = [\"\u002F\u002Fthird_party\u002Fpy\u002Fjax:license\"])\n\nlicenses([\"notice\"])\n\ncc_shared_library(\n   name = \"jax\",\n   deps = [\n       \":main\",\n   ],\n   visibility = [\"\u002F\u002Fvisibility:public\"],\n)\n\ncc_library(\n   name = \"main\",\n   srcs = [\"main.cc\"],\n   hdrs = [\"main.h\"],\n   tags = [\"manual\"],\n   copts = [\"-fvisibility=default\"],\n   visibility = [\"\u002F\u002Fvisibility:public\"],\n   deps = [\n       \"@xla\u002F\u002Fxla:literal\",\n       \"@xla\u002F\u002Fxla:literal_util\",\n       \"@xla\u002F\u002Fxla:statusor\",\n       \"@xla\u002F\u002Fxla\u002Fpjrt:pjrt_client\",\n       \"@xla\u002F\u002Fxla\u002Fpjrt\u002Fcpu:cpu_client\",\n       \"@xla\u002F\u002Fxla\u002Ftools:hlo_module_loader\",\n       \"@tsl\u002F\u002Ftsl\u002Fplatform:logging\",\n       \"@tsl\u002F\u002Ftsl\u002Fplatform:platform_port\",\n   ],\n)\n",[751,931,929],{"__ignoreMap":753},[687,933,934,935,916],{},"Lastly, we’ll want to add these two imports to our ",[751,936,937],{},"main.cc",[744,939,942],{"className":940,"code":941,"language":749},[747],"#include \"tsl\u002Fplatform\u002Finit_main.h\" \n#include \"tsl\u002Fplatform\u002Flogging.h\"\n",[751,943,941],{"__ignoreMap":753},[687,945,946,947,952],{},"We’ll need to make sure that Bazel is installed on our system. It’s a very convenient build manager that handles fetching libraries and recompilation of specific sources on code changes without rebuilding the entire solution. It can be installed following the official guides ",[696,948,951],{"href":949,"rel":950},"https:\u002F\u002Fbazel.build\u002Finstall",[700],"here",".",[687,954,955],{},"After that is done from the root jax repository directory we can run:",[744,957,960],{"className":958,"code":959,"language":749},[747],"bazel build examples\u002Fjax_cpp:jax --experimental_repo_remote_exec  \n--check_visibility=false\n",[751,961,959],{"__ignoreMap":753},[687,963,964,965,968],{}," This will build our target called ",[751,966,967],{},"jax"," and produce artifacts in jax\u002Fbazel-bin\u002Fexamples\u002Fjax_cpp. You should see a file called libjax.dylib in that directory.",[682,970],{"id":971},"_1",[682,973,975],{"id":974},"using-dart-ffi-to-communicate-with-the-c-code","Using Dart FFI to communicate with the C++ code",[687,977,978],{},"Now that we have the C++ library ready we can load it in and use it from any environment we want. In this example, however, we will be using Dart’s FFI.",[687,980,981,982,985],{},"Inside our project we will create a file called ",[751,983,984],{},"jax.dart"," and copy the code just below.",[744,987,990],{"className":988,"code":989,"language":749},[747],"import 'dart:ffi'; \nimport 'package:dynamic_library\u002Fdynamic_library.dart';\n\ntypedef FooCFunc = Int32 Function(Int32 bar); \ntypedef FooDartFunc = int Function(int bar);\n\n\u002F\u002F\u002F Class for housing FFI behaviors \nclass JAX { \n  late final DynamicLibrary dylib; \n\n  \u002F\u002F Create OCR FFI Class from loaded dynamic library \n  JAX() { \n    dylib = loadDynamicLibrary(libraryName: 'jax'); \n  } \n\n  \u002F\u002F Create dart wrapper to C function \n  Function get _bar => dylib.lookupFunction\u003CFooCFunc, FooDartFunc>('bar'); \n\n  int bar(int foo) { \n    return _bar(foo); \n  } \n}\n",[751,991,989],{"__ignoreMap":753},[687,993,994,995,998,999,1002],{},"The DynamicLibrary class comes from the ffi package and will allow us to communicate with the C++ code. Importantly the loadDynamicLibrary method will look for the library on the root path of your project by default. We simply copy over the compiled library and paste into the same directory that has our ",[751,996,997],{},"pubspec.yaml",". The ",[751,1000,1001],{},".lookupFunction"," method requires us to define the input and output types that will be used to communicate between Dart and C++. This is a simple case where the input and output are just integers.",[687,1004,1005,1006,916],{},"Since we’re using a package dynamic_libraries to load in our dylib we’ll also need to include in in our ",[751,1007,997],{},[744,1009,1012],{"className":1010,"code":1011,"language":749},[747],"dynamic_library: ^0.9.0\n",[751,1013,1011],{"__ignoreMap":753},[687,1015,1016,1017,1020],{},"To test out our code we can create a unit test that will call the ",[751,1018,1019],{},".bar"," method of the JAX class. Since we’re not actually returning anything to Dart at this point and only print out the results we should see output similar to this in the console:",[744,1022,1025],{"className":1023,"code":1024,"language":749},[747],"Testing started at 3:50 PM ...\nWARNING: All log messages before absl::InitializeLog() is called are written to STDERR\nI0000 00:00:1730818248.061020 126198617 cpu_client.cc:467] TfrtCpuClient created.\nI0000 00:00:1730818248.076400 126198617 main.cc:109] result = (\nf32[2,2] {\n  { 1.5, 2 },\n  { 3.5, 5 }\n}\n)\nI0000 00:00:1730818248.076495 126198617 cpu_client.cc:470] TfrtCpuClient destroyed.\n\nProcess finished with exit code 0\n",[751,1026,1024],{"__ignoreMap":753},[682,1028],{"id":1029},"_2",[682,1031,1033],{"id":1032},"next-steps","Next Steps",[687,1035,1036],{},"We’ve demonstrated that any arbitrary (jittable) JAX code can be executed in C++ from Dart. What’s left is to write more complicated algorithms in JAX that we want to be optimized and run on an accelerator.",[687,1038,1039],{},"Apart from the obvious machine learning applications, some other examples include but are not limited to search (eg. A*), combinatorial optimization algorithms (scheduling, partition), or even classical image processing methods like finding edges with a Canny filter!",[687,1041,1042],{},"An additional benefit of using JAX is that those algorithms can be written by Data Scientists and Machine Learning Engineers directly in Python without the need to involve an experienced C\u002FC++ programmer to rewrite them for production applications.",[687,1044,1045],{},"This can save a lot of development time and headaches since resolving C++ bugs and memory leaks can be very troublesome.",{"title":753,"searchDepth":1047,"depth":1047,"links":1048},2,[1049,1050,1051,1052,1053,1054,1055,1056,1057,1058],{"id":684,"depth":1047,"text":685},{"id":720,"depth":1047,"text":721},{"id":753,"depth":1047,"text":753},{"id":803,"depth":1047,"text":804},{"id":816,"depth":1047,"text":817},{"id":905,"depth":1047,"text":906},{"id":971,"depth":1047,"text":753},{"id":974,"depth":1047,"text":975},{"id":1029,"depth":1047,"text":753},{"id":1032,"depth":1047,"text":1033},"Software Development","2024-11-21T00:00:00.000Z","Learn how to build machine learning apps using JAX, Python, and Dart with efficient XLA compilation and FFI integration.",false,"md","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Frunning-a-jax-program-from-dart-using-c-ffi\u002Fhero.png",{},"\u002Fblog\u002Frunning-a-jax-program-from-dart-using-c-ffi",{"title":673,"description":1061},"blog\u002Frunning-a-jax-program-from-dart-using-c-ffi","pCCSM-KjD7i1J-qmI4NlM-wfM4HLc1VLRF-1kc_ZeKk",{"id":1071,"title":674,"body":1072,"description":1083,"draft":1062,"extension":1063,"meta":1084,"navigation":32,"path":1085,"photo":1086,"photoAlt":676,"seo":1087,"stem":1088,"__hash__":1089},"authors\u002Fauthors\u002Fdominik-huss.md",{"type":679,"value":1073,"toc":1081},[1074],[687,1075,1076,1080],{},[1077,1078,1079],"strong",{},"Dominik Huss's"," main area of interest in ML is centered around everything discrete, (semi-)symbolic and deeply rooted in theoretical maths. Most importantly ways to describe and view different models through the lense of symmetries and invariances. At Pieces he likes to have an input in everything graphs related, as well as bridging the gap between research and production by utilizing his computer science background. When not working, Dominik likes to play board games with friends, run\u002Fparticipate in RPG sessions, cook and do some sports.",{"title":753,"searchDepth":1047,"depth":1047,"links":1082},[],"Dominik Huss's main area of interest in ML is centered around everything discrete, (semi-)symbolic and deeply rooted in theoretical maths. Most importantly ways to describe and view different models through the lense of symmetries and invariances. At Pieces he likes to have an input in everything graphs related, as well as bridging the gap between research and production by utilizing his computer science background. When not working, Dominik likes to play board games with friends, run\u002Fparticipate in RPG sessions, cook and do some sports.",{},"\u002Fauthors\u002Fdominik-huss","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fauthors\u002Fdominik-huss.png",{"title":674,"description":1083},"authors\u002Fdominik-huss","7E-BQDnM_P22Cd3zqYMlS94LGswXJRrFIOlHKbH3vsQ",{"left":1091,"top":1091,"width":1092,"height":1092,"rotate":1091,"vFlip":1062,"hFlip":1062,"body":1093},0,24,"\u003Cpath fill=\"currentColor\" d=\"m7.825 13l4.9 4.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-6.6-6.6q-.15-.15-.213-.325T4.426 12t.063-.375t.212-.325l6.6-6.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L7.825 11H19q.425 0 .713.288T20 12t-.288.713T19 13z\"\u002F>"]