blob: cc21d0ec7e535925480fa49a8a2e73b20eff2d84 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en" data-content_root="" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>The Arrow C Device data interface &#8212; Apache Arrow v17.0.0.dev52</title>
<script data-cfasync="false">
document.documentElement.dataset.mode = localStorage.getItem("mode") || "";
document.documentElement.dataset.theme = localStorage.getItem("theme") || "light";
</script>
<!-- Loaded before other Sphinx assets -->
<link href="../_static/styles/theme.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../_static/styles/bootstrap.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../_static/styles/pydata-sphinx-theme.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../_static/vendor/fontawesome/6.5.1/css/all.min.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../_static/vendor/fontawesome/6.5.1/webfonts/fa-solid-900.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../_static/vendor/fontawesome/6.5.1/webfonts/fa-brands-400.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../_static/vendor/fontawesome/6.5.1/webfonts/fa-regular-400.woff2" />
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css" />
<link rel="stylesheet" type="text/css" href="../_static/theme_overrides.css" />
<!-- Pre-loaded scripts that we'll load fully later -->
<link rel="preload" as="script" href="../_static/scripts/bootstrap.js?digest=8d27b9dea8ad943066ae" />
<link rel="preload" as="script" href="../_static/scripts/pydata-sphinx-theme.js?digest=8d27b9dea8ad943066ae" />
<script src="../_static/vendor/fontawesome/6.5.1/js/all.min.js?digest=8d27b9dea8ad943066ae"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/clipboard.min.js"></script>
<script src="../_static/copybutton.js"></script>
<script src="../_static/design-tabs.js"></script>
<script>DOCUMENTATION_OPTIONS.pagename = 'format/CDeviceDataInterface';</script>
<script>
DOCUMENTATION_OPTIONS.theme_version = '0.15.2';
DOCUMENTATION_OPTIONS.theme_switcher_json_url = '/docs/_static/versions.json';
DOCUMENTATION_OPTIONS.theme_switcher_version_match = 'dev/';
DOCUMENTATION_OPTIONS.show_version_warning_banner = true;
</script>
<link rel="canonical" href="https://arrow.apache.org/docs/format/CDeviceDataInterface.html" />
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Arrow Flight RPC" href="Flight.html" />
<link rel="prev" title="The Arrow C stream interface" href="CStreamInterface.html" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="docsearch:language" content="en"/>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '20']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body data-bs-spy="scroll" data-bs-target=".bd-toc-nav" data-offset="180" data-bs-root-margin="0px 0px -60%" data-default-mode="">
<a id="pst-skip-link" class="skip-link" href="#main-content">Skip to main content</a>
<div id="pst-scroll-pixel-helper"></div>
<button type="button" class="btn rounded-pill" id="pst-back-to-top">
<i class="fa-solid fa-arrow-up"></i>
Back to top
</button>
<input type="checkbox"
class="sidebar-toggle"
name="__primary"
id="__primary"/>
<label class="overlay overlay-primary" for="__primary"></label>
<input type="checkbox"
class="sidebar-toggle"
name="__secondary"
id="__secondary"/>
<label class="overlay overlay-secondary" for="__secondary"></label>
<div class="search-button__wrapper">
<div class="search-button__overlay"></div>
<div class="search-button__search-container">
<form class="bd-search d-flex align-items-center"
action="../search.html"
method="get">
<i class="fa-solid fa-magnifying-glass"></i>
<input type="search"
class="form-control"
name="q"
id="search-input"
placeholder="Search the docs ..."
aria-label="Search the docs ..."
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"/>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd>K</kbd></span>
</form></div>
</div>
<header class="bd-header navbar navbar-expand-lg bd-navbar">
<div class="bd-header__inner bd-page-width">
<label class="sidebar-toggle primary-toggle" for="__primary">
<span class="fa-solid fa-bars"></span>
</label>
<div class="col-lg-3 navbar-header-items__start">
<div class="navbar-item">
<a class="navbar-brand logo" href="../index.html">
<img src="../_static/arrow.png" class="logo__image only-light" alt="Apache Arrow v17.0.0.dev52 - Home"/>
<script>document.write(`<img src="../_static/arrow-dark.png" class="logo__image only-dark" alt="Apache Arrow v17.0.0.dev52 - Home"/>`);</script>
</a></div>
</div>
<div class="col-lg-9 navbar-header-items">
<div class="me-auto navbar-header-items__center">
<div class="navbar-item">
<nav class="navbar-nav">
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item current active">
<a class="nav-link nav-internal" href="index.html">
Specifications
</a>
</li>
<li class="nav-item">
<a class="nav-link nav-internal" href="../developers/index.html">
Development
</a>
</li>
<li class="nav-item dropdown">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="pst-nav-more-links">
Implementations
</button>
<ul id="pst-nav-more-links" class="dropdown-menu">
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../c_glib/index.html">
C/GLib
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../cpp/index.html">
C++
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/csharp/README.md">
C#
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://pkg.go.dev/github.com/apache/arrow/go/v17">
Go
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../java/index.html">
Java
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../js/index.html">
JavaScript
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/julia/">
Julia
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/matlab/README.md">
MATLAB
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/nanoarrow/">
nanoarrow
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../python/index.html">
Python
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../r/index.html">
R
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/ruby/README.md">
Ruby
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://docs.rs/crate/arrow/">
Rust
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../status.html">
Implementation Status
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/cpp/">
C++ cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/java/">
Java cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/py/">
Python cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/r/">
R cookbook
</a>
</li>
</ul>
</li>
</ul>
</nav></div>
</div>
<div class="navbar-header-items__end">
<div class="navbar-item navbar-persistent--container">
<script>
document.write(`
<button class="btn navbar-btn search-button-field search-button__button" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
`);
</script>
</div>
<div class="navbar-item">
<script>
document.write(`
<div class="version-switcher__container dropdown">
<button id="pst-version-switcher-button-2"
type="button"
class="version-switcher__button btn btn-sm navbar-btn dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-2"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-2"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-2">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div>
`);
</script></div>
<div class="navbar-item">
<script>
document.write(`
<button class="btn btn-sm navbar-btn theme-switch-button" title="light/dark" aria-label="light/dark" data-bs-placement="bottom" data-bs-toggle="tooltip">
<span class="theme-switch nav-link" data-mode="light"><i class="fa-solid fa-sun fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="dark"><i class="fa-solid fa-moon fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="auto"><i class="fa-solid fa-circle-half-stroke fa-lg"></i></span>
</button>
`);
</script></div>
<div class="navbar-item"><ul class="navbar-icon-links navbar-nav"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://twitter.com/ApacheArrow" title="X" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-x-twitter fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">X</span></a>
</li>
</ul></div>
</div>
</div>
<div class="navbar-persistent--mobile">
<script>
document.write(`
<button class="btn navbar-btn search-button-field search-button__button" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
`);
</script>
</div>
<label class="sidebar-toggle secondary-toggle" for="__secondary" tabindex="0">
<span class="fa-solid fa-outdent"></span>
</label>
</div>
</header>
<div class="bd-container">
<div class="bd-container__inner bd-page-width">
<div class="bd-sidebar-primary bd-sidebar">
<div class="sidebar-header-items sidebar-primary__section">
<div class="sidebar-header-items__center">
<div class="navbar-item">
<nav class="navbar-nav">
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item current active">
<a class="nav-link nav-internal" href="index.html">
Specifications
</a>
</li>
<li class="nav-item">
<a class="nav-link nav-internal" href="../developers/index.html">
Development
</a>
</li>
<li class="nav-item dropdown">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="pst-nav-more-links-2">
Implementations
</button>
<ul id="pst-nav-more-links-2" class="dropdown-menu">
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../c_glib/index.html">
C/GLib
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../cpp/index.html">
C++
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/csharp/README.md">
C#
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://pkg.go.dev/github.com/apache/arrow/go/v17">
Go
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../java/index.html">
Java
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../js/index.html">
JavaScript
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/julia/">
Julia
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/matlab/README.md">
MATLAB
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/nanoarrow/">
nanoarrow
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../python/index.html">
Python
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../r/index.html">
R
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/ruby/README.md">
Ruby
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://docs.rs/crate/arrow/">
Rust
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../status.html">
Implementation Status
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/cpp/">
C++ cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/java/">
Java cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/py/">
Python cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/r/">
R cookbook
</a>
</li>
</ul>
</li>
</ul>
</nav></div>
</div>
<div class="sidebar-header-items__end">
<div class="navbar-item">
<script>
document.write(`
<div class="version-switcher__container dropdown">
<button id="pst-version-switcher-button-3"
type="button"
class="version-switcher__button btn btn-sm navbar-btn dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-3"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-3"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-3">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div>
`);
</script></div>
<div class="navbar-item">
<script>
document.write(`
<button class="btn btn-sm navbar-btn theme-switch-button" title="light/dark" aria-label="light/dark" data-bs-placement="bottom" data-bs-toggle="tooltip">
<span class="theme-switch nav-link" data-mode="light"><i class="fa-solid fa-sun fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="dark"><i class="fa-solid fa-moon fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="auto"><i class="fa-solid fa-circle-half-stroke fa-lg"></i></span>
</button>
`);
</script></div>
<div class="navbar-item"><ul class="navbar-icon-links navbar-nav"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://twitter.com/ApacheArrow" title="X" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-x-twitter fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">X</span></a>
</li>
</ul></div>
</div>
</div>
<div class="sidebar-primary-items__start sidebar-primary__section">
<div class="sidebar-primary-item">
<nav class="bd-docs-nav bd-links"
aria-label="Section Navigation">
<p class="bd-links__title" role="heading" aria-level="1">Section Navigation</p>
<div class="bd-toc-item navbar-nav"><ul class="current nav bd-sidenav">
<li class="toctree-l1"><a class="reference internal" href="Versioning.html">Format Versioning and Stability</a></li>
<li class="toctree-l1"><a class="reference internal" href="Columnar.html">Arrow Columnar Format</a></li>
<li class="toctree-l1"><a class="reference internal" href="CanonicalExtensions.html">Canonical Extension Types</a></li>
<li class="toctree-l1"><a class="reference internal" href="Other.html">Other Data Structures</a></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="CDataInterface.html">The Arrow C data interface</a><input class="toctree-checkbox" id="toctree-checkbox-1" name="toctree-checkbox-1" type="checkbox"/><label class="toctree-toggle" for="toctree-checkbox-1"><i class="fa-solid fa-chevron-down"></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="CDataInterface/PyCapsuleInterface.html">The Arrow PyCapsule Interface</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="CStreamInterface.html">The Arrow C stream interface</a></li>
<li class="toctree-l1 current active"><a class="current reference internal" href="#">The Arrow C Device data interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="Flight.html">Arrow Flight RPC</a></li>
<li class="toctree-l1"><a class="reference internal" href="FlightSql.html">Arrow Flight SQL</a></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="ADBC.html">ADBC: Arrow Database Connectivity</a><input class="toctree-checkbox" id="toctree-checkbox-2" name="toctree-checkbox-2" type="checkbox"/><label class="toctree-toggle" for="toctree-checkbox-2"><i class="fa-solid fa-chevron-down"></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="ADBC/C.html">ADBC C API Specification</a></li>
<li class="toctree-l2"><a class="reference internal" href="ADBC/Go.html">ADBC Go API Specification</a></li>
<li class="toctree-l2"><a class="reference internal" href="ADBC/Java.html">ADBC Java API Specification</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Changing.html">Changing the Apache Arrow Format Specification</a></li>
<li class="toctree-l1"><a class="reference internal" href="Integration.html">Integration Testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="Glossary.html">Glossary</a></li>
</ul>
</div>
</nav></div>
</div>
<div class="sidebar-primary-items__end sidebar-primary__section">
</div>
<div id="rtd-footer-container"></div>
</div>
<main id="main-content" class="bd-main">
<div class="bd-content">
<div class="bd-article-container">
<div class="bd-header-article">
<div class="header-article-items header-article__inner">
<div class="header-article-items__start">
<div class="header-article-item">
<nav aria-label="Breadcrumb">
<ul class="bd-breadcrumbs">
<li class="breadcrumb-item breadcrumb-home">
<a href="../index.html" class="nav-link" aria-label="Home">
<i class="fa-solid fa-home"></i>
</a>
</li>
<li class="breadcrumb-item"><a href="index.html" class="nav-link">Specifications</a></li>
<li class="breadcrumb-item active" aria-current="page">The Arrow C...</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div id="searchbox"></div>
<article class="bd-article">
<section id="the-arrow-c-device-data-interface">
<span id="c-device-data-interface"></span><h1>The Arrow C Device data interface<a class="headerlink" href="#the-arrow-c-device-data-interface" title="Permalink to this heading">#</a></h1>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>The Arrow C Device Data Interface should be considered experimental</p>
</div>
<section id="rationale">
<h2>Rationale<a class="headerlink" href="#rationale" title="Permalink to this heading">#</a></h2>
<p>The current <a class="reference internal" href="CDataInterface.html#c-data-interface"><span class="std std-ref">C Data Interface</span></a>, and most
implementations of it, make the assumption that all data buffers provided
are CPU buffers. Since Apache Arrow is designed to be a universal in-memory
format for representing tabular (“columnar”) data, there will be the desire
to leverage this data on non-CPU hardware such as GPUs. One example of such
a case is the <a class="reference external" href="https://docs.rapids.ai/api/cudf/stable/">RAPIDS cuDF library</a> which uses the Arrow memory format with
CUDA for NVIDIA GPUs. Since copying data from host to device and back is
expensive, the ideal would be to be able to leave the data on the device
for as long as possible, even when passing it between runtimes and
libraries.</p>
<p>The Arrow C Device data interface builds on the existing C data interface
by adding a very small, stable set of C definitions to it. These definitions
are equivalents to the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowArrayStream</span></code> structures
from the C Data Interface which add members to allow specifying the device
type and pass necessary information to synchronize with the producer.
For non-C/C++ languages and runtimes, translating the C definitions to
corresponding C FFI declarations should be just as simple as with the
current C data interface.</p>
<p>Applications and libraries can then use Arrow schemas and Arrow formatted
memory on non-CPU devices to exchange data just as easily as they do
now with CPU data. This will enable leaving data on those devices longer
and avoiding costly copies back and forth between the host and device
just to leverage new libraries and runtimes.</p>
<section id="goals">
<h3>Goals<a class="headerlink" href="#goals" title="Permalink to this heading">#</a></h3>
<ul class="simple">
<li><p>Expose an ABI-stable interface built on the existing C data interface.</p></li>
<li><p>Make it easy for third-party projects to implement support with little
initial investment.</p></li>
<li><p>Allow zero-copy sharing of Arrow formatted device memory between
independent runtimes and components running in the same process.</p></li>
<li><p>Avoid the need for one-to-one adaptation layers such as the
<a class="reference external" href="https://numba.readthedocs.io/en/stable/cuda/cuda_array_interface.html">CUDA Array Interface</a> for Python processes to pass CUDA data.</p></li>
<li><p>Enable integration without explicit dependencies (either at compile-time
or runtime) on the Arrow software project itself.</p></li>
</ul>
<p>The intent is for the Arrow C Device data interface to expand the reach
of the current C data interface, allowing it to also become the standard
low-level building block for columnar processing on devices like GPUs or
FPGAs.</p>
</section>
</section>
<section id="structure-definitions">
<h2>Structure definitions<a class="headerlink" href="#structure-definitions" title="Permalink to this heading">#</a></h2>
<p>Because this is built on the C data interface, the C Device data interface
uses the <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structures as defined in the
<a class="reference internal" href="CDataInterface.html#c-data-interface-struct-defs"><span class="std std-ref">C data interface spec</span></a>. It then adds the
following free-standing definitions. Like the rest of the Arrow project,
they are available under the Apache License 2.0.</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifndef ARROW_C_DEVICE_DATA_INTERFACE</span>
<span class="cp">#define ARROW_C_DEVICE_DATA_INTERFACE</span>
<span class="c1">// Device type for the allocated memory</span>
<span class="k">typedef</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">ArrowDeviceType</span><span class="p">;</span>
<span class="c1">// CPU device, same as using ArrowArray directly</span>
<span class="cp">#define ARROW_DEVICE_CPU 1</span>
<span class="c1">// CUDA GPU Device</span>
<span class="cp">#define ARROW_DEVICE_CUDA 2</span>
<span class="c1">// Pinned CUDA CPU memory by cudaMallocHost</span>
<span class="cp">#define ARROW_DEVICE_CUDA_HOST 3</span>
<span class="c1">// OpenCL Device</span>
<span class="cp">#define ARROW_DEVICE_OPENCL 4</span>
<span class="c1">// Vulkan buffer for next-gen graphics</span>
<span class="cp">#define ARROW_DEVICE_VULKAN 7</span>
<span class="c1">// Metal for Apple GPU</span>
<span class="cp">#define ARROW_DEVICE_METAL 8</span>
<span class="c1">// Verilog simulator buffer</span>
<span class="cp">#define ARROW_DEVICE_VPI 9</span>
<span class="c1">// ROCm GPUs for AMD GPUs</span>
<span class="cp">#define ARROW_DEVICE_ROCM 10</span>
<span class="c1">// Pinned ROCm CPU memory allocated by hipMallocHost</span>
<span class="cp">#define ARROW_DEVICE_ROCM_HOST 11</span>
<span class="c1">// Reserved for extension</span>
<span class="c1">//</span>
<span class="c1">// used to quickly test extension devices, semantics</span>
<span class="c1">// can differ based on implementation</span>
<span class="cp">#define ARROW_DEVICE_EXT_DEV 12</span>
<span class="c1">// CUDA managed/unified memory allocated by cudaMallocManaged</span>
<span class="cp">#define ARROW_DEVICE_CUDA_MANAGED 13</span>
<span class="c1">// Unified shared memory allocated on a oneAPI</span>
<span class="c1">// non-partitioned device.</span>
<span class="c1">//</span>
<span class="c1">// A call to the oneAPI runtime is required to determine the</span>
<span class="c1">// device type, the USM allocation type and the sycl context</span>
<span class="c1">// that it is bound to.</span>
<span class="cp">#define ARROW_DEVICE_ONEAPI 14</span>
<span class="c1">// GPU support for next-gen WebGPU standard</span>
<span class="cp">#define ARROW_DEVICE_WEBGPU 15</span>
<span class="c1">// Qualcomm Hexagon DSP</span>
<span class="cp">#define ARROW_DEVICE_HEXAGON 16</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArray</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowArray</span><span class="w"> </span><span class="n">array</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int64_t</span><span class="w"> </span><span class="n">device_id</span><span class="p">;</span>
<span class="w"> </span><span class="n">ArrowDeviceType</span><span class="w"> </span><span class="n">device_type</span><span class="p">;</span>
<span class="w"> </span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">sync_event</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// reserved bytes for future expansion</span>
<span class="w"> </span><span class="kt">int64_t</span><span class="w"> </span><span class="n">reserved</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>
<span class="p">};</span>
<span class="cp">#endif </span><span class="c1">// ARROW_C_DEVICE_DATA_INTERFACE</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The canonical guard <code class="docutils literal notranslate"><span class="pre">ARROW_C_DEVICE_DATA_INTERFACE</span></code> is meant to avoid
duplicate definitions if two projects copy the definitions in their own
headers, and a third-party project includes from these two projects. It
is therefore important that this guard is kept exactly as-is when these
definitions are copied.</p>
</div>
<section id="arrowdevicetype">
<h3>ArrowDeviceType<a class="headerlink" href="#arrowdevicetype" title="Permalink to this heading">#</a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">ArrowDeviceType</span></code> typedef is used to indicate what type of device the
provided memory buffers were allocated on. This, in conjunction with the
<code class="docutils literal notranslate"><span class="pre">device_id</span></code>, should be sufficient to reference the correct data buffers.</p>
<p>We then use macros to define values for different device types. The provided
macro values are compatible with the widely used <a class="reference external" href="https://dmlc.github.io/dlpack/latest/c_api.html#c-api">dlpack</a> <code class="docutils literal notranslate"><span class="pre">DLDeviceType</span></code>
definition values, using the same value for each as the equivalent
<code class="docutils literal notranslate"><span class="pre">kDL&lt;type&gt;</span></code> enum from <code class="docutils literal notranslate"><span class="pre">dlpack.h</span></code>. The list will be kept in sync with those
equivalent enum values over time to ensure compatibility, rather than
potentially diverging. To avoid the Arrow project having to be in the
position of vetting new hardware devices, new additions should first be
added to dlpack before we add a corresponding macro here.</p>
<p>To ensure predictability with the ABI, we use macros instead of an <code class="docutils literal notranslate"><span class="pre">enum</span></code>
so the storage type is not compiler dependent.</p>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_CPU">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_CPU</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_CPU" title="Permalink to this definition">#</a><br /></dt>
<dd><p>CPU Device, equivalent to just using <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> directly instead of
using <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code>.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_CUDA">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_CUDA</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_CUDA" title="Permalink to this definition">#</a><br /></dt>
<dd><p>A <a class="reference external" href="https://developer.nvidia.com/cuda-toolkit">CUDA</a> GPU Device. This could represent data allocated either with the
runtime library (<code class="docutils literal notranslate"><span class="pre">cudaMalloc</span></code>) or the device driver (<code class="docutils literal notranslate"><span class="pre">cuMemAlloc</span></code>).</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_CUDA_HOST">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_CUDA_HOST</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_CUDA_HOST" title="Permalink to this definition">#</a><br /></dt>
<dd><p>CPU memory that was pinned and page-locked by CUDA by using
<code class="docutils literal notranslate"><span class="pre">cudaMallocHost</span></code> or <code class="docutils literal notranslate"><span class="pre">cuMemAllocHost</span></code>.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_OPENCL">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_OPENCL</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_OPENCL" title="Permalink to this definition">#</a><br /></dt>
<dd><p>Data allocated on the device by using the <a class="reference external" href="https://www.khronos.org/opencl/">OpenCL (Open Computing Language)</a>
framework.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_VULKAN">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_VULKAN</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_VULKAN" title="Permalink to this definition">#</a><br /></dt>
<dd><p>Data allocated by the <a class="reference external" href="https://www.vulkan.org/">Vulkan</a> framework and libraries.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_METAL">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_METAL</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_METAL" title="Permalink to this definition">#</a><br /></dt>
<dd><p>Data on Apple GPU devices using the <a class="reference external" href="https://developer.apple.com/metal/">Metal</a> framework and libraries.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_VPI">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_VPI</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_VPI" title="Permalink to this definition">#</a><br /></dt>
<dd><p>Indicates usage of a Verilog simulator buffer.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_ROCM">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_ROCM</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_ROCM" title="Permalink to this definition">#</a><br /></dt>
<dd><p>An AMD device using the <a class="reference external" href="https://www.amd.com/en/graphics/servers-solutions-rocm">ROCm</a> stack.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_ROCM_HOST">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_ROCM_HOST</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_ROCM_HOST" title="Permalink to this definition">#</a><br /></dt>
<dd><p>CPU memory that was pinned and page-locked by ROCm by using <code class="docutils literal notranslate"><span class="pre">hipMallocHost</span></code>.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_EXT_DEV">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_EXT_DEV</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_EXT_DEV" title="Permalink to this definition">#</a><br /></dt>
<dd><p>This value is an escape-hatch for devices to extend which aren’t
currently represented otherwise. Producers would need to provide
additional information/context specific to the device if using
this device type. This is used to quickly test extension devices
and semantics can differ based on the implementation.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_CUDA_MANAGED">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_CUDA_MANAGED</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_CUDA_MANAGED" title="Permalink to this definition">#</a><br /></dt>
<dd><p>CUDA managed/unified memory which is allocated by <code class="docutils literal notranslate"><span class="pre">cudaMallocManaged</span></code>.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_ONEAPI">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_ONEAPI</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_ONEAPI" title="Permalink to this definition">#</a><br /></dt>
<dd><p>Unified shared memory allocated on an Intel <a class="reference external" href="https://www.intel.com/content/www/us/en/developer/tools/oneapi/overview.html">oneAPI</a> non-partitioned
device. A call to the <code class="docutils literal notranslate"><span class="pre">oneAPI</span></code> runtime is required to determine
the specific device type, the USM allocation type and the sycl context
that it is bound to.</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_WEBGPU">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_WEBGPU</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_WEBGPU" title="Permalink to this definition">#</a><br /></dt>
<dd><p>GPU support for next-gen WebGPU standards</p>
</dd></dl>
<dl class="c macro">
<dt class="sig sig-object c" id="c.ARROW_DEVICE_HEXAGON">
<span class="sig-name descname"><span class="n"><span class="pre">ARROW_DEVICE_HEXAGON</span></span></span><a class="headerlink" href="#c.ARROW_DEVICE_HEXAGON" title="Permalink to this definition">#</a><br /></dt>
<dd><p>Data allocated on a Qualcomm Hexagon DSP device.</p>
</dd></dl>
</section>
<section id="the-arrowdevicearray-structure">
<h3>The ArrowDeviceArray structure<a class="headerlink" href="#the-arrowdevicearray-structure" title="Permalink to this heading">#</a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code> structure embeds the C data <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure
and adds additional information necessary for consumers to use the data. It
has the following fields:</p>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArray.array">
<span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">ArrowArray</span></span><span class="w"> </span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArray</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">array</span></span></span><a class="headerlink" href="#c.ArrowDeviceArray.array" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Mandatory.</em> The allocated array data. The values in the <code class="docutils literal notranslate"><span class="pre">void**</span></code> buffers (along
with the buffers of any children) are what is allocated on the device.
The buffer values should be device pointers. The rest of the structure
should be accessible to the CPU.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">private_data</span></code> and <code class="docutils literal notranslate"><span class="pre">release</span></code> callback of this structure should
contain any necessary information and structures related to freeing
the array according to the device it is allocated on, rather than
having a separate release callback and <code class="docutils literal notranslate"><span class="pre">private_data</span></code> pointer here.</p>
</dd></dl>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArray.device_id">
<span class="n"><span class="pre">int64_t</span></span><span class="w"> </span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArray</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">device_id</span></span></span><a class="headerlink" href="#c.ArrowDeviceArray.device_id" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Mandatory.</em> The device id to identify a specific device if multiple devices of this
type are on the system. The semantics of the id will be hardware dependent,
but we use an <code class="docutils literal notranslate"><span class="pre">int64_t</span></code> to future-proof the id as devices change over time.</p>
<p>For device types that do not have an intrinsic notion of a device identifier (e.g.,
<code class="docutils literal notranslate"><span class="pre">ARROW_DEVICE_CPU</span></code>), it is recommended to use a <code class="docutils literal notranslate"><span class="pre">device_id</span></code> of -1 as a
convention.</p>
</dd></dl>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArray.device_type">
<span class="n"><span class="pre">ArrowDeviceType</span></span><span class="w"> </span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArray</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">device_type</span></span></span><a class="headerlink" href="#c.ArrowDeviceArray.device_type" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Mandatory.</em> The type of the device which can access the buffers in the array.</p>
</dd></dl>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArray.sync_event">
<span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArray</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">sync_event</span></span></span><a class="headerlink" href="#c.ArrowDeviceArray.sync_event" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Optional.</em> An event-like object to synchronize on if needed.</p>
<p>Many devices, like GPUs, are primarily asynchronous with respect to
CPU processing. As such, in order to safely access device memory, it is often
necessary to have an object to synchronize processing with. Since
different devices will use different types to specify this, we use a
<code class="docutils literal notranslate"><span class="pre">void*</span></code> which can be coerced into a pointer to whatever the device
appropriate type is.</p>
<p>If synchronization is not needed, this can be null. If this is non-null
then it MUST be used to call the appropriate sync method for the device
(e.g. <code class="docutils literal notranslate"><span class="pre">cudaStreamWaitEvent</span></code> or <code class="docutils literal notranslate"><span class="pre">hipStreamWaitEvent</span></code>) before attempting
to access the memory in the buffers.</p>
<p>If an event is provided, then the producer MUST ensure that the exported
data is available on the device before the event is triggered. The
consumer SHOULD wait on the event before trying to access the exported
data.</p>
</dd></dl>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p>The <a class="reference internal" href="#c-device-data-interface-event-types"><span class="std std-ref">synchronization event types</span></a>
section below.</p>
</div>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArray.reserved">
<span class="n"><span class="pre">int64_t</span></span><span class="w"> </span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArray</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">reserved</span></span></span><span class="p"><span class="pre">[</span></span><span class="m"><span class="pre">3</span></span><span class="p"><span class="pre">]</span></span><a class="headerlink" href="#c.ArrowDeviceArray.reserved" title="Permalink to this definition">#</a><br /></dt>
<dd><p>As non-CPU development expands, there may be a need to expand this
structure. In order to do so without potentially breaking ABI changes,
we reserve 24 bytes at the end of the object. These bytes MUST be zero’d
out after initialization by the producer in order to ensure safe
evolution of the ABI in the future.</p>
</dd></dl>
</section>
<section id="synchronization-event-types">
<span id="c-device-data-interface-event-types"></span><h3>Synchronization event types<a class="headerlink" href="#synchronization-event-types" title="Permalink to this heading">#</a></h3>
<p>The table below lists the expected event types for each device type.
If no event type is supported (“N/A”), then the <code class="docutils literal notranslate"><span class="pre">sync_event</span></code> member
should always be null.</p>
<p>Remember that the event <em>CAN</em> be null if synchronization is not needed
to access the data.</p>
<table class="table">
<thead>
<tr class="row-odd"><th class="head"><p>Device Type</p></th>
<th class="head"><p>Actual Event Type</p></th>
<th class="head"><p>Notes</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>ARROW_DEVICE_CPU</p></td>
<td><p>N/A</p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p>ARROW_DEVICE_CUDA</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">cudaEvent_t*</span></code></p></td>
<td></td>
</tr>
<tr class="row-even"><td><p>ARROW_DEVICE_CUDA_HOST</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">cudaEvent_t*</span></code></p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p>ARROW_DEVICE_OPENCL</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">cl_event*</span></code></p></td>
<td></td>
</tr>
<tr class="row-even"><td><p>ARROW_DEVICE_VULKAN</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">VkEvent*</span></code></p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p>ARROW_DEVICE_METAL</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">MTLEvent*</span></code></p></td>
<td></td>
</tr>
<tr class="row-even"><td><p>ARROW_DEVICE_VPI</p></td>
<td><p>N/A</p></td>
<td><ol class="arabic simple">
<li></li>
</ol>
</td>
</tr>
<tr class="row-odd"><td><p>ARROW_DEVICE_ROCM</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">hipEvent_t*</span></code></p></td>
<td></td>
</tr>
<tr class="row-even"><td><p>ARROW_DEVICE_ROCM_HOST</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">hipEvent_t*</span></code></p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p>ARROW_DEVICE_EXT_DEV</p></td>
<td></td>
<td><ol class="arabic simple" start="2">
<li></li>
</ol>
</td>
</tr>
<tr class="row-even"><td><p>ARROW_DEVICE_CUDA_MANAGED</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">cudaEvent_t*</span></code></p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p>ARROW_DEVICE_ONEAPI</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">sycl::event*</span></code></p></td>
<td></td>
</tr>
<tr class="row-even"><td><p>ARROW_DEVICE_WEBGPU</p></td>
<td><p>N/A</p></td>
<td><ol class="arabic simple">
<li></li>
</ol>
</td>
</tr>
<tr class="row-odd"><td><p>ARROW_DEVICE_HEXAGON</p></td>
<td><p>N/A</p></td>
<td><ol class="arabic simple">
<li></li>
</ol>
</td>
</tr>
</tbody>
</table>
<p>Notes:</p>
<ul class="simple">
<li><p>(1) Currently unknown if framework has an event type to support.</p></li>
<li><p>(2) Extension Device has producer defined semantics and thus if
synchronization is needed for an extension device, the producer
should document the type.</p></li>
</ul>
</section>
</section>
<section id="semantics">
<h2>Semantics<a class="headerlink" href="#semantics" title="Permalink to this heading">#</a></h2>
<section id="memory-management">
<h3>Memory management<a class="headerlink" href="#memory-management" title="Permalink to this heading">#</a></h3>
<p>First and foremost: Out of everything in this interface, it is <em>only</em> the
data buffers themselves which reside in device memory (i.e. the <code class="docutils literal notranslate"><span class="pre">buffers</span></code>
member of the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> struct). Everything else should be in CPU
memory.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code> structure contains an <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> object which
itself has <a class="reference internal" href="CDataInterface.html#c-data-interface-semantics"><span class="std std-ref">specific semantics</span></a> for releasing
memory. The term <em>“base structure”</em> below refers to the <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code>
object that is passed directly between the producer and consumer – not any
child structure thereof.</p>
<p>It is intended for the base structure to be stack- or heap-allocated by the
<em>consumer</em>. In this case, the producer API should take a pointer to the
consumer-allocated structure.</p>
<p>However, any data pointed to by the struct MUST be allocated and maintained
by the producer. This includes the <code class="docutils literal notranslate"><span class="pre">sync_event</span></code> member if it is not null,
along with any pointers in the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> object as usual. Data lifetime
is managed through the <code class="docutils literal notranslate"><span class="pre">release</span></code> callback of the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> member.</p>
<p>For an <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code>, the semantics of a released structure and the
callback semantics are identical to those for
<a class="reference internal" href="CDataInterface.html#c-data-interface-released"><span class="std std-ref">ArrowArray itself</span></a>. Any producer specific context
information necessary for releasing the device data buffers, in addition to
any allocated event, should be stored in the <code class="docutils literal notranslate"><span class="pre">private_data</span></code> member of
the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> and managed by the <code class="docutils literal notranslate"><span class="pre">release</span></code> callback.</p>
<section id="moving-an-array">
<h4>Moving an array<a class="headerlink" href="#moving-an-array" title="Permalink to this heading">#</a></h4>
<p>The consumer can <em>move</em> the <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code> structure by bitwise copying
or shallow member-wise copying. Then it MUST mark the source structure released
by setting the <code class="docutils literal notranslate"><span class="pre">release</span></code> member of the embedded <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure to
<code class="docutils literal notranslate"><span class="pre">NULL</span></code>, but <em>without</em> calling that release callback. This ensures that only
one live copy of the struct is active at any given time and that lifetime is
correctly communicated to the producer.</p>
<p>As usual, the release callback will be called on the destination structure
when it is not needed anymore.</p>
</section>
</section>
<section id="record-batches">
<h3>Record batches<a class="headerlink" href="#record-batches" title="Permalink to this heading">#</a></h3>
<p>As with the C data interface itself, a record batch can be trivially considered
as an equivalent struct array. In this case the metadata of the top-level
<code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> can be used for schema-level metadata of the record batch.</p>
</section>
<section id="mutability">
<h3>Mutability<a class="headerlink" href="#mutability" title="Permalink to this heading">#</a></h3>
<p>Both the producer and the consumer SHOULD consider the exported data (that
is, the data reachable on the device through the <code class="docutils literal notranslate"><span class="pre">buffers</span></code> member of
the embedded <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code>) to be immutable, as either party could otherwise
see inconsistent data while the other is mutating it.</p>
</section>
<section id="synchronization">
<h3>Synchronization<a class="headerlink" href="#synchronization" title="Permalink to this heading">#</a></h3>
<p>If the <code class="docutils literal notranslate"><span class="pre">sync_event</span></code> member is non-NULL, the consumer should not attempt
to access or read the data until they have synchronized on that event. If
the <code class="docutils literal notranslate"><span class="pre">sync_event</span></code> member is NULL, then it MUST be safe to access the data
without any synchronization necessary on the part of the consumer.</p>
</section>
</section>
<section id="c-producer-example">
<h2>C producer example<a class="headerlink" href="#c-producer-example" title="Permalink to this heading">#</a></h2>
<section id="exporting-a-simple-int32-device-array">
<h3>Exporting a simple <code class="docutils literal notranslate"><span class="pre">int32</span></code> device array<a class="headerlink" href="#exporting-a-simple-int32-device-array" title="Permalink to this heading">#</a></h3>
<p>Export a non-nullable <code class="docutils literal notranslate"><span class="pre">int32</span></code> type with empty metadata. An example of this
can be seen in the <a class="reference internal" href="CDataInterface.html#c-data-interface-export-int32-schema"><span class="std std-ref">C data interface docs directly</span></a>.</p>
<p>To export the data itself, we transfer ownership to the consumer through
the release callback. This example will use CUDA, but the equivalent calls
could be used for any device:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">release_int32_device_array</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowArray</span><span class="o">*</span><span class="w"> </span><span class="n">array</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">array</span><span class="o">-&gt;</span><span class="n">n_buffers</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">2</span><span class="p">);</span>
<span class="w"> </span><span class="c1">// destroy the event</span>
<span class="w"> </span><span class="n">cudaEvent_t</span><span class="o">*</span><span class="w"> </span><span class="n">ev_ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">cudaEvent_t</span><span class="o">*</span><span class="p">)(</span><span class="n">array</span><span class="o">-&gt;</span><span class="n">private_data</span><span class="p">);</span>
<span class="w"> </span><span class="n">cudaError_t</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cudaEventDestroy</span><span class="p">(</span><span class="o">*</span><span class="n">ev_ptr</span><span class="p">);</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">status</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">cudaSuccess</span><span class="p">);</span>
<span class="w"> </span><span class="n">free</span><span class="p">(</span><span class="n">ev_ptr</span><span class="p">);</span>
<span class="w"> </span><span class="c1">// free the buffers and the buffers array</span>
<span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cudaFree</span><span class="p">(</span><span class="n">array</span><span class="o">-&gt;</span><span class="n">buffers</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">status</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">cudaSuccess</span><span class="p">);</span>
<span class="w"> </span><span class="n">free</span><span class="p">(</span><span class="n">array</span><span class="o">-&gt;</span><span class="n">buffers</span><span class="p">);</span>
<span class="w"> </span><span class="c1">// mark released</span>
<span class="w"> </span><span class="n">array</span><span class="o">-&gt;</span><span class="n">release</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">export_int32_device_array</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">cudaAllocedPtr</span><span class="p">,</span>
<span class="w"> </span><span class="n">cudaStream_t</span><span class="w"> </span><span class="n">stream</span><span class="p">,</span>
<span class="w"> </span><span class="kt">int64_t</span><span class="w"> </span><span class="n">length</span><span class="p">,</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArray</span><span class="o">*</span><span class="w"> </span><span class="n">array</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// get device id</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">device</span><span class="p">;</span>
<span class="w"> </span><span class="n">cudaError_t</span><span class="w"> </span><span class="n">status</span><span class="p">;</span>
<span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cudaGetDevice</span><span class="p">(</span><span class="o">&amp;</span><span class="n">device</span><span class="p">);</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">status</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">cudaSuccess</span><span class="p">);</span>
<span class="w"> </span><span class="n">cudaEvent_t</span><span class="o">*</span><span class="w"> </span><span class="n">ev_ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">cudaEvent_t</span><span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">cudaEvent_t</span><span class="p">));</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">ev_ptr</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">);</span>
<span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cudaEventCreate</span><span class="p">(</span><span class="n">ev_ptr</span><span class="p">);</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">status</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">cudaSuccess</span><span class="p">);</span>
<span class="w"> </span><span class="c1">// record event on the stream, assuming that the passed in</span>
<span class="w"> </span><span class="c1">// stream is where the work to produce the data will be processing.</span>
<span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cudaEventRecord</span><span class="p">(</span><span class="o">*</span><span class="n">ev_ptr</span><span class="p">,</span><span class="w"> </span><span class="n">stream</span><span class="p">);</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">status</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">cudaSuccess</span><span class="p">);</span>
<span class="w"> </span><span class="n">memset</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArray</span><span class="p">));</span>
<span class="w"> </span><span class="c1">// initialize fields</span>
<span class="w"> </span><span class="o">*</span><span class="n">array</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArray</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">.</span><span class="n">array</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowArray</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">.</span><span class="n">length</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">length</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">null_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">offset</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">n_buffers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">n_children</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">children</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">dictionary</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span>
<span class="w"> </span><span class="c1">// bookkeeping</span>
<span class="w"> </span><span class="p">.</span><span class="n">release</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">release_int32_device_array</span><span class="p">,</span>
<span class="w"> </span><span class="c1">// store the event pointer as private data in the array</span>
<span class="w"> </span><span class="c1">// so that we can access it in the release callback.</span>
<span class="w"> </span><span class="p">.</span><span class="n">private_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)(</span><span class="n">ev_ptr</span><span class="p">),</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">.</span><span class="n">device_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">int64_t</span><span class="p">)(</span><span class="n">device</span><span class="p">),</span>
<span class="w"> </span><span class="p">.</span><span class="n">device_type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ARROW_DEVICE_CUDA</span><span class="p">,</span>
<span class="w"> </span><span class="c1">// pass the event pointer to the consumer</span>
<span class="w"> </span><span class="p">.</span><span class="n">sync_event</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)(</span><span class="n">ev_ptr</span><span class="p">),</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="c1">// allocate list of buffers</span>
<span class="w"> </span><span class="n">array</span><span class="o">-&gt;</span><span class="n">array</span><span class="p">.</span><span class="n">buffers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">array</span><span class="o">-&gt;</span><span class="n">array</span><span class="p">.</span><span class="n">n_buffers</span><span class="p">);</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">array</span><span class="o">-&gt;</span><span class="n">array</span><span class="p">.</span><span class="n">buffers</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">);</span>
<span class="w"> </span><span class="n">array</span><span class="o">-&gt;</span><span class="n">array</span><span class="p">.</span><span class="n">buffers</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="w"> </span><span class="n">array</span><span class="o">-&gt;</span><span class="n">array</span><span class="p">.</span><span class="n">buffers</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cudaAllocedPtr</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// calling the release callback should be done using the array member</span>
<span class="c1">// of the device array.</span>
<span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">release_device_array_helper</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArray</span><span class="o">*</span><span class="w"> </span><span class="n">arr</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">arr</span><span class="o">-&gt;</span><span class="n">array</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="o">&amp;</span><span class="n">arr</span><span class="o">-&gt;</span><span class="n">array</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
</section>
<section id="device-stream-interface">
<h2>Device Stream Interface<a class="headerlink" href="#device-stream-interface" title="Permalink to this heading">#</a></h2>
<p>Like the <a class="reference internal" href="CStreamInterface.html#c-stream-interface"><span class="std std-ref">C stream interface</span></a>, the C Device data
interface also specifies a higher-level structure for easing communication
of streaming data within a single process.</p>
<section id="id1">
<h3>Semantics<a class="headerlink" href="#id1" title="Permalink to this heading">#</a></h3>
<p>An Arrow C device stream exposes a streaming source of data chunks, each with
the same schema. Chunks are obtained by calling a blocking pull-style iteration
function. It is expected that all chunks should be providing data on the same
device type (but not necessarily the same device id). If it is necessary
to provide a stream of data on multiple device types, a producer should
provide a separate stream object for each device type.</p>
</section>
<section id="structure-definition">
<h3>Structure definition<a class="headerlink" href="#structure-definition" title="Permalink to this heading">#</a></h3>
<p>The C device stream interface is defined by a single <code class="docutils literal notranslate"><span class="pre">struct</span></code> definition:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifndef ARROW_C_DEVICE_STREAM_INTERFACE</span>
<span class="cp">#define ARROW_C_DEVICE_STREAM_INTERFACE</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArrayStream</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// device type that all arrays will be accessible from</span>
<span class="w"> </span><span class="n">ArrowDeviceType</span><span class="w"> </span><span class="n">device_type</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// callbacks</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">get_schema</span><span class="p">)(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArrayStream</span><span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowSchema</span><span class="o">*</span><span class="p">);</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">get_next</span><span class="p">)(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArrayStream</span><span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArray</span><span class="o">*</span><span class="p">);</span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">get_last_error</span><span class="p">)(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArrayStream</span><span class="o">*</span><span class="p">);</span>
<span class="w"> </span><span class="c1">// release callback</span>
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">release</span><span class="p">)(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowDeviceArrayStream</span><span class="o">*</span><span class="p">);</span>
<span class="w"> </span><span class="c1">// opaque producer-specific data</span>
<span class="w"> </span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">private_data</span><span class="p">;</span>
<span class="p">};</span>
<span class="cp">#endif </span><span class="c1">// ARROW_C_DEVICE_STREAM_INTERFACE</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The canonical guard <code class="docutils literal notranslate"><span class="pre">ARROW_C_DEVICE_STREAM_INTERFACE</span></code> is meant to avoid
duplicate definitions if two projects copy the C device stream interface
definitions into their own headers, and a third-party project includes
from these two projects. It is therefore important that this guard is
kept exactly as-is when these definitions are copied.</p>
</div>
<section id="the-arrowdevicearraystream-structure">
<h4>The ArrowDeviceArrayStream structure<a class="headerlink" href="#the-arrowdevicearraystream-structure" title="Permalink to this heading">#</a></h4>
<p>The <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream</span></code> provides a device type that can access the
resulting data along with the required callbacks to interact with a
streaming source of Arrow arrays. It has the following fields:</p>
<dl class="c member">
<dt class="sig sig-object c" id="c.device_type">
<span class="n"><span class="pre">ArrowDeviceType</span></span><span class="w"> </span><span class="sig-name descname"><span class="n"><span class="pre">device_type</span></span></span><a class="headerlink" href="#c.device_type" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Mandatory.</em> The device type that this stream produces data on. All
<code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code> s that are produced by this stream should have the
same device type as is set here. This is a convenience for the consumer
to not have to check every array that is retrieved and instead allows
higher-level coding constructs for streams.</p>
</dd></dl>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArrayStream.get_schema">
<span class="kt"><span class="pre">int</span></span><span class="w"> </span><span class="p"><span class="pre">(</span></span><span class="p"><span class="pre">*</span></span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">get_schema</span></span></span><span class="p"><span class="pre">)</span></span><span class="p"><span class="pre">(</span></span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">*</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">ArrowSchema</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">out</span></span><span class="p"><span class="pre">)</span></span><a class="headerlink" href="#c.ArrowDeviceArrayStream.get_schema" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Mandatory.</em> This callback allows the consumer to query the schema of
the chunks of data in the stream. The schema is the same for all data
chunks.</p>
<p>This callback must NOT be called on a released <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream</span></code>.</p>
<p><em>Return value:</em> 0 on success, a non-zero
<a class="reference internal" href="CStreamInterface.html#c-stream-interface-error-codes"><span class="std std-ref">error code</span></a> otherwise.</p>
</dd></dl>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArrayStream.get_next">
<span class="kt"><span class="pre">int</span></span><span class="w"> </span><span class="p"><span class="pre">(</span></span><span class="p"><span class="pre">*</span></span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">get_next</span></span></span><span class="p"><span class="pre">)</span></span><span class="p"><span class="pre">(</span></span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">*</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">ArrowDeviceArray</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">out</span></span><span class="p"><span class="pre">)</span></span><a class="headerlink" href="#c.ArrowDeviceArrayStream.get_next" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Mandatory.</em> This callback allows the consumer to get the next chunk of
data in the stream.</p>
<p>This callback must NOT be called on a released <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream</span></code>.</p>
<p>The next chunk of data MUST be accessible from a device type matching the
<code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream.device_type</span></code>.</p>
<p><em>Return value:</em> 0 on success, a non-zero
<a class="reference internal" href="CStreamInterface.html#c-stream-interface-error-codes"><span class="std std-ref">error code</span></a> otherwise.</p>
<p>On success, the consumer must check whether the <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code>’s
embedded <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> is marked <a class="reference internal" href="CDataInterface.html#c-data-interface-released"><span class="std std-ref">released</span></a>.
If the embedded <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray.array</span></code> is released, then the end of the
stream has been reached. Otherwise, the <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code> contains a
valid data chunk.</p>
</dd></dl>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArrayStream.get_last_error">
<span class="k"><span class="pre">const</span></span><span class="w"> </span><span class="kt"><span class="pre">char</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="p"><span class="pre">(</span></span><span class="p"><span class="pre">*</span></span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">get_last_error</span></span></span><span class="p"><span class="pre">)</span></span><span class="p"><span class="pre">(</span></span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">*</span></span><span class="p"><span class="pre">)</span></span><a class="headerlink" href="#c.ArrowDeviceArrayStream.get_last_error" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Mandatory.</em> This callback allows the consumer to get a textual description
of the last error.</p>
<p>This callback must ONLY be called if the last operation on the
<code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream</span></code> returned an error. It must NOT be called on a
released <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream</span></code>.</p>
<p><em>Return value:</em> a pointer to a NULL-terminated character string
(UTF8-encoded). NULL can also be returned if no detailed description is
available.</p>
<p>The returned pointer is only guaranteed to be valid until the next call
of one of the stream’s callbacks. The character string it points to should
be copied to consumer-managed storage if it is intended to survive longer.</p>
</dd></dl>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArrayStream.release">
<span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="p"><span class="pre">(</span></span><span class="p"><span class="pre">*</span></span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">release</span></span></span><span class="p"><span class="pre">)</span></span><span class="p"><span class="pre">(</span></span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">*</span></span><span class="p"><span class="pre">)</span></span><a class="headerlink" href="#c.ArrowDeviceArrayStream.release" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Mandatory.</em> A pointer to a producer-provided release callback.</p>
</dd></dl>
<dl class="c member">
<dt class="sig sig-object c" id="c.ArrowDeviceArrayStream.private_data">
<span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="sig-prename descclassname"><span class="n"><span class="pre">ArrowDeviceArrayStream</span></span><span class="p"><span class="pre">.</span></span></span><span class="sig-name descname"><span class="n"><span class="pre">private_data</span></span></span><a class="headerlink" href="#c.ArrowDeviceArrayStream.private_data" title="Permalink to this definition">#</a><br /></dt>
<dd><p><em>Optional.</em> An opaque pointer to producer-provided private data.</p>
<p>Consumers MUST NOT process this member. Lifetime of this member is
handled by the producer, and especially by the release callback.</p>
</dd></dl>
</section>
<section id="result-lifetimes">
<h4>Result lifetimes<a class="headerlink" href="#result-lifetimes" title="Permalink to this heading">#</a></h4>
<p>The data returned by the <code class="docutils literal notranslate"><span class="pre">get_schema</span></code> and <code class="docutils literal notranslate"><span class="pre">get_next</span></code> callbacks must be
released independently. Their lifetimes are not tied to that of
<code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream</span></code>.</p>
</section>
<section id="stream-lifetime">
<h4>Stream lifetime<a class="headerlink" href="#stream-lifetime" title="Permalink to this heading">#</a></h4>
<p>Lifetime of the C stream is managed using a release callback with similar
usage as in <a class="reference internal" href="CDataInterface.html#c-data-interface-released"><span class="std std-ref">C data interface</span></a>.</p>
</section>
<section id="thread-safety">
<h4>Thread safety<a class="headerlink" href="#thread-safety" title="Permalink to this heading">#</a></h4>
<p>The stream source is not assumed to be thread-safe. Consumers wanting to
call <code class="docutils literal notranslate"><span class="pre">get_next</span></code> from several threads should ensure those calls are
serialized.</p>
</section>
</section>
</section>
<section id="interoperability-with-other-interchange-formats">
<h2>Interoperability with other interchange formats<a class="headerlink" href="#interoperability-with-other-interchange-formats" title="Permalink to this heading">#</a></h2>
<p>Other interchange APIs, such as the <a class="reference external" href="https://numba.readthedocs.io/en/stable/cuda/cuda_array_interface.html">CUDA Array Interface</a>, include
members to pass the shape and the data types of the data buffers being
exported. This information is necessary to interpret the raw bytes in the
device data buffers that are being shared. Rather than store the
shape / types of the data alongside the <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code>, users
should utilize the existing <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> structure to pass any data
type and shape information.</p>
</section>
<section id="updating-this-specification">
<h2>Updating this specification<a class="headerlink" href="#updating-this-specification" title="Permalink to this heading">#</a></h2>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Since this specification is still considered experimental, there is the
(still very low) possibility it might change slightly. The reason for
tagging this as “experimental” is because we don’t know what we don’t know.
Work and research was done to ensure a generic ABI compatible with many
different frameworks, but it is always possible something was missed.
Once this is supported in an official Arrow release and usage is observed
to confirm there aren’t any modifications necessary, the “experimental”
tag will be removed and the ABI frozen.</p>
</div>
<p>Once this specification is supported in an official Arrow release, the C ABI
is frozen. This means that the <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code> structure definition
should not change in any way – including adding new members.</p>
<p>Backwards-compatible changes are allowed, for example new macro values for
<code class="xref c c-type docutils literal notranslate"><span class="pre">ArrowDeviceType</span></code> or converting the reserved 24 bytes into a
different type/member without changing the size of the structure.</p>
<p>Any incompatible changes should be part of a new specification, for example
<code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayV2</span></code>.</p>
</section>
</section>
</article>
<footer class="prev-next-footer">
<div class="prev-next-area">
<a class="left-prev"
href="CStreamInterface.html"
title="previous page">
<i class="fa-solid fa-angle-left"></i>
<div class="prev-next-info">
<p class="prev-next-subtitle">previous</p>
<p class="prev-next-title">The Arrow C stream interface</p>
</div>
</a>
<a class="right-next"
href="Flight.html"
title="next page">
<div class="prev-next-info">
<p class="prev-next-subtitle">next</p>
<p class="prev-next-title">Arrow Flight RPC</p>
</div>
<i class="fa-solid fa-angle-right"></i>
</a>
</div>
</footer>
</div>
<div class="bd-sidebar-secondary bd-toc"><div class="sidebar-secondary-items sidebar-secondary__inner">
<div class="sidebar-secondary-item">
<div
id="pst-page-navigation-heading-2"
class="page-toc tocsection onthispage">
<i class="fa-solid fa-list"></i> On this page
</div>
<nav class="bd-toc-nav page-toc" aria-labelledby="pst-page-navigation-heading-2">
<ul class="visible nav section-nav flex-column">
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#rationale">Rationale</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#goals">Goals</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#structure-definitions">Structure definitions</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#arrowdevicetype">ArrowDeviceType</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#the-arrowdevicearray-structure">The ArrowDeviceArray structure</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#synchronization-event-types">Synchronization event types</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#semantics">Semantics</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#memory-management">Memory management</a><ul class="nav section-nav flex-column">
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#moving-an-array">Moving an array</a></li>
</ul>
</li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#record-batches">Record batches</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#mutability">Mutability</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#synchronization">Synchronization</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#c-producer-example">C producer example</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#exporting-a-simple-int32-device-array">Exporting a simple <code class="docutils literal notranslate"><span class="pre">int32</span></code> device array</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#device-stream-interface">Device Stream Interface</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#id1">Semantics</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#structure-definition">Structure definition</a><ul class="nav section-nav flex-column">
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#the-arrowdevicearraystream-structure">The ArrowDeviceArrayStream structure</a></li>
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#result-lifetimes">Result lifetimes</a></li>
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#stream-lifetime">Stream lifetime</a></li>
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#thread-safety">Thread safety</a></li>
</ul>
</li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#interoperability-with-other-interchange-formats">Interoperability with other interchange formats</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#updating-this-specification">Updating this specification</a></li>
</ul>
</nav></div>
<div class="sidebar-secondary-item">
<div class="tocsection editthispage">
<a href="https://github.com/apache/arrow/edit/main/docs/source/format/CDeviceDataInterface.rst">
<i class="fa-solid fa-pencil"></i>
Edit on GitHub
</a>
</div>
</div>
</div></div>
</div>
<footer class="bd-footer-content">
</footer>
</main>
</div>
</div>
<!-- Scripts loaded after <body> so the DOM is not blocked -->
<script src="../_static/scripts/bootstrap.js?digest=8d27b9dea8ad943066ae"></script>
<script src="../_static/scripts/pydata-sphinx-theme.js?digest=8d27b9dea8ad943066ae"></script>
<footer class="bd-footer">
<div class="bd-footer__inner bd-page-width">
<div class="footer-items__start">
<div class="footer-item">
<p class="copyright">
© Copyright 2016-2024 Apache Software Foundation.
Apache Arrow, Arrow, Apache, the Apache feather logo, and the Apache Arrow project logo are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries.
<br/>
</p>
</div>
<div class="footer-item">
<p class="sphinx-version">
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 6.2.0.
<br/>
</p>
</div>
</div>
<div class="footer-items__end">
<div class="footer-item">
<p class="theme-version">
Built with the <a href="https://pydata-sphinx-theme.readthedocs.io/en/stable/index.html">PyData Sphinx Theme</a> 0.15.2.
</p></div>
</div>
</div>
</footer>
</body>
</html>