@@ -38,13 +38,15 @@ class PsiformerOptions(networks.BaseNetworkOptions):
3838 mlp_hidden_dims: Tuple of sizes of hidden dimension of the MLP. Note that
3939 this does not include the final projection to the embedding dimension.
4040 use_layer_norm: If true, include a layer norm on both attention and MLP.
41+ tf32: If true, use TF32-precision matmuls where appropriate.
4142 """
4243
4344 num_layers : int = 2
4445 num_heads : int = 4
4546 heads_dim : int = 64
4647 mlp_hidden_dims : Tuple [int , ...] = (256 ,)
4748 use_layer_norm : bool = False
49+ tf32 : bool = False
4850
4951
5052def make_layer_norm () -> ...:
@@ -68,12 +70,15 @@ def apply(params: networks.ParamTree,
6870 return init , apply
6971
7072
71- def make_multi_head_attention (num_heads : int , heads_dim : int ) -> ...:
73+ def make_multi_head_attention (num_heads : int ,
74+ heads_dim : int ,
75+ tf32 : bool = False ) -> ...:
7276 """FermiNet-style version of MultiHeadAttention."""
77+ prec = jax .lax .DotAlgorithmPreset .TF32_TF32_F32 if tf32 else None
7378
7479 # Linear layer plus reshape final dimensions to num_heads, heads_dim.
7580 def linear_projection (x : jnp .ndarray , weights : jnp .ndarray ) -> jnp .ndarray :
76- y = jnp .dot (x , weights )
81+ y = jnp .dot (x , weights , precision = prec )
7782 return y .reshape (* x .shape [:- 1 ], num_heads , heads_dim )
7883
7984 def init (key : chex .PRNGKey ,
@@ -123,13 +128,13 @@ def apply(params: networks.ParamTree, query: jnp.ndarray, key: jnp.ndarray,
123128 k = linear_projection (key , params ['k_w' ])
124129 v = linear_projection (value , params ['v_w' ])
125130
126- attn_logits = jnp .einsum ('...thd,...Thd->...htT' , q , k )
131+ attn_logits = jnp .einsum ('...thd,...Thd->...htT' , q , k , precision = prec )
127132 scale = 1. / np .sqrt (heads_dim )
128133 attn_logits *= scale
129134
130135 attn_weights = jax .nn .softmax (attn_logits )
131136
132- attn = jnp .einsum ('...htT,...Thd->...thd' , attn_weights , v )
137+ attn = jnp .einsum ('...htT,...Thd->...thd' , attn_weights , v , precision = prec )
133138
134139 # Concatenate attention matrix of all heads into a single vector.
135140 # Shape [..., q_index_dim, num_heads * heads_dim]
@@ -174,10 +179,11 @@ def make_self_attention_block(num_layers: int,
174179 num_heads : int ,
175180 heads_dim : int ,
176181 mlp_hidden_dims : Tuple [int , ...],
177- use_layer_norm : bool = False ) -> ...:
182+ use_layer_norm : bool = False ,
183+ tf32 : bool = False ) -> ...:
178184 """Create a QKV self-attention block."""
179185 attention_init , attention_apply = make_multi_head_attention (
180- num_heads , heads_dim )
186+ num_heads , heads_dim , tf32 )
181187 if use_layer_norm :
182188 layer_norm_init , layer_norm_apply = make_layer_norm ()
183189 mlp_init , mlp_apply = make_mlp ()
@@ -253,6 +259,7 @@ def make_psiformer_layers(
253259 heads_dim = options .heads_dim ,
254260 mlp_hidden_dims = options .mlp_hidden_dims ,
255261 use_layer_norm = options .use_layer_norm ,
262+ tf32 = options .tf32 ,
256263 )
257264
258265 def init (key : chex .PRNGKey ) -> Tuple [int , networks .ParamTree ]:
@@ -342,6 +349,7 @@ def make_fermi_net(
342349 heads_dim : int ,
343350 mlp_hidden_dims : Tuple [int , ...],
344351 use_layer_norm : bool ,
352+ tf32 : bool ,
345353) -> networks .Network :
346354 """Psiformer with stacked Self Attention layers.
347355
@@ -365,6 +373,7 @@ def make_fermi_net(
365373 heads_dim: Embedding dimension per-head for self-attention.
366374 mlp_hidden_dims: Tuple of hidden dimensions of the MLP.
367375 use_layer_norm: If true, use layer_norm on both attention and MLP.
376+ tf32: If true, use TF32-precision matmuls where appropriate.
368377
369378 Returns:
370379 Network object containing init, apply, orbitals, options, where init and
@@ -404,6 +413,7 @@ def make_fermi_net(
404413 heads_dim = heads_dim ,
405414 mlp_hidden_dims = mlp_hidden_dims ,
406415 use_layer_norm = use_layer_norm ,
416+ tf32 = tf32 ,
407417 ) # pytype: disable=wrong-keyword-args
408418
409419 psiformer_layers = make_psiformer_layers (nspins , charges .shape [0 ], options )
0 commit comments