chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
.. _guide-message-passing-api:
|
||||
|
||||
2.1 Built-in Functions and Message Passing APIs
|
||||
-----------------------------------------------
|
||||
|
||||
:ref:`(中文版) <guide_cn-message-passing-api>`
|
||||
|
||||
In DGL, **message function** takes a single argument ``edges``,
|
||||
which is an :class:`~dgl.udf.EdgeBatch` instance. During message passing,
|
||||
DGL generates it internally to represent a batch of edges. It has three
|
||||
members ``src``, ``dst`` and ``data`` to access features of source nodes,
|
||||
destination nodes, and edges, respectively.
|
||||
|
||||
**reduce function** takes a single argument ``nodes``, which is a
|
||||
:class:`~dgl.udf.NodeBatch` instance. During message passing,
|
||||
DGL generates it internally to represent a batch of nodes. It has member
|
||||
``mailbox`` to access the messages received for the nodes in the batch.
|
||||
Some of the most common reduce operations include ``sum``, ``max``, ``min``, etc.
|
||||
|
||||
**update function** takes a single argument ``nodes`` as described above.
|
||||
This function operates on the aggregation result from ``reduce function``, typically
|
||||
combining it with a node’s original feature at the the last step and saving the result
|
||||
as a node feature.
|
||||
|
||||
DGL has implemented commonly used message functions and reduce functions
|
||||
as **built-in** in the namespace ``dgl.function``. In general, DGL
|
||||
suggests using built-in functions **whenever possible** since they are
|
||||
heavily optimized and automatically handle dimension broadcasting.
|
||||
|
||||
If your message passing functions cannot be implemented with built-ins,
|
||||
you can implement user-defined message/reduce function (aka. **UDF**).
|
||||
|
||||
Built-in message functions can be unary or binary. DGL supports ``copy``
|
||||
for unary. For binary funcs, DGL supports ``add``, ``sub``, ``mul``, ``div``,
|
||||
``dot``. The naming convention for message built-in funcs is that ``u``
|
||||
represents ``src`` nodes, ``v`` represents ``dst`` nodes, and ``e`` represents ``edges``.
|
||||
The parameters for those functions are strings indicating the input and output field names for
|
||||
the corresponding nodes and edges. The list of supported built-in functions
|
||||
can be found in :ref:`api-built-in`. For example, to add the ``hu`` feature from src
|
||||
nodes and ``hv`` feature from dst nodes then save the result on the edge
|
||||
at ``he`` field, one can use built-in function ``dgl.function.u_add_v('hu', 'hv', 'he')``.
|
||||
This is equivalent to the Message UDF:
|
||||
|
||||
.. code::
|
||||
|
||||
def message_func(edges):
|
||||
return {'he': edges.src['hu'] + edges.dst['hv']}
|
||||
|
||||
Built-in reduce functions support operations ``sum``, ``max``, ``min``,
|
||||
and ``mean``. Reduce functions usually have two parameters, one
|
||||
for field name in ``mailbox``, one for field name in node features, both
|
||||
are strings. For example, ``dgl.function.sum('m', 'h')`` is equivalent
|
||||
to the Reduce UDF that sums up the message ``m``:
|
||||
|
||||
.. code::
|
||||
|
||||
import torch
|
||||
def reduce_func(nodes):
|
||||
return {'h': torch.sum(nodes.mailbox['m'], dim=1)}
|
||||
|
||||
For advanced usage of UDF, see :ref:`apiudf`.
|
||||
|
||||
It is also possible to invoke only edge-wise computation by :meth:`~dgl.DGLGraph.apply_edges`
|
||||
without invoking message passing. :meth:`~dgl.DGLGraph.apply_edges` takes a message function
|
||||
for parameter and by default updates the features of all edges. For example:
|
||||
|
||||
.. code::
|
||||
|
||||
import dgl.function as fn
|
||||
graph.apply_edges(fn.u_add_v('el', 'er', 'e'))
|
||||
|
||||
For message passing, :meth:`~dgl.DGLGraph.update_all` is a high-level
|
||||
API that merges message generation, message aggregation and node update
|
||||
in a single call, which leaves room for optimization as a whole.
|
||||
|
||||
The parameters for :meth:`~dgl.DGLGraph.update_all` are a message function, a
|
||||
reduce function and an update function. One can call update function outside of
|
||||
``update_all`` and not specify it in invoking :meth:`~dgl.DGLGraph.update_all`.
|
||||
DGL recommends this approach since the update function can usually be
|
||||
written as pure tensor operations to make the code concise. For
|
||||
example:
|
||||
|
||||
.. code::
|
||||
|
||||
def update_all_example(graph):
|
||||
# store the result in graph.ndata['ft']
|
||||
graph.update_all(fn.u_mul_e('ft', 'a', 'm'),
|
||||
fn.sum('m', 'ft'))
|
||||
# Call update function outside of update_all
|
||||
final_ft = graph.ndata['ft'] * 2
|
||||
return final_ft
|
||||
|
||||
This call will generate the messages ``m`` by multiply src node features
|
||||
``ft`` and edge features ``a``, sum up the messages ``m`` to update node
|
||||
features ``ft``, and finally multiply ``ft`` by 2 to get the result
|
||||
``final_ft``. After the call, DGL will clean the intermediate messages ``m``.
|
||||
The math formula for the above function is:
|
||||
|
||||
.. math:: {final\_ft}_i = 2 * \sum_{j\in\mathcal{N}(i)} ({ft}_j * a_{ji})
|
||||
|
||||
DGL's built-in functions support floating point data types, i.e. the feature must
|
||||
be ``half`` (``float16``) /``float``/``double`` tensors.
|
||||
``float16`` data type support is disabled by default as it has a minimum GPU
|
||||
compute capacity requirement of ``sm_53`` (Pascal, Volta, Turing and Ampere
|
||||
architectures).
|
||||
|
||||
User can enable float16 for mixed precision training by compiling DGL from source
|
||||
(see :doc:`Mixed Precision Training <mixed_precision>` tutorial for details).
|
||||
Reference in New Issue
Block a user