For the complete documentation index, see llms.txt. This page is also available as Markdown.

Data Types

The DataType enum, per-array typing, type casting, mixed precision, and migration from global data type

One of the most significant changes in M2.1 is the move from a global data type to per-array data types. Every INDArray now carries its own DataType, and operations are type-aware. This page covers the full DataType enum, how to create typed arrays, how to cast between types, and how to take advantage of mixed precision training.


The DataType Enum

All numeric types in ND4J are represented by the enum org.nd4j.linalg.api.buffer.DataType. Import it with:

import org.nd4j.linalg.api.buffer.DataType;

Floating-Point Types

Floating-point types are used for neural network weights, activations, and most numeric computation.

Enum Constant
Bits
Description

DOUBLE

64

IEEE 754 double-precision float. Highest precision, largest memory footprint.

FLOAT

32

IEEE 754 single-precision float. Default type. Best balance of precision and performance on most hardware.

FLOAT16

16

Half-precision float. Reduced memory and bandwidth; supported on modern NVIDIA GPUs and some CPUs. Same constant as the deprecated HALF.

BFLOAT16

16

Brain float 16. Same 8-bit exponent range as FLOAT, but only 7 mantissa bits. Numerically safer than FLOAT16 for training. Supported on TPUs, A100/H100 GPUs, and recent Intel CPUs.

Signed Integer Types

Enum Constant
Bits
Notes

INT64

64

64-bit signed integer. Same constant as the deprecated LONG.

INT32

32

32-bit signed integer. Same constant as the deprecated INT.

INT16

16

16-bit signed integer. Same constant as the deprecated SHORT.

INT8

8

8-bit signed integer, range −128 to 127. Same constant as the deprecated BYTE.

Unsigned Integer Types

Enum Constant
Bits

UINT64

64

UINT32

32

UINT16

16

UINT8

8 — range 0 to 255. Same constant as the deprecated UBYTE.

Other Types

Enum Constant
Description

BOOL

Boolean — stores true/false per element. Used by comparison ops that return masks.

UTF8

Variable-length UTF-8 string data. Used for label arrays and metadata.

COMPRESSED

Internal placeholder for compressed arrays. Not for direct use.

UNKNOWN

Sentinel value. Indicates an uninitialized or invalid type.

Deprecated Aliases

Several names from earlier releases are still present in the enum but are annotated @Deprecated. They map to the same underlying constant as their preferred replacement.

Deprecated Name
Preferred Name

HALF

FLOAT16

LONG

INT64

INT

INT32

SHORT

INT16

BYTE

INT8

UBYTE

UINT8

FLOAT16 and HALF are literally the same enum constant — FLOAT16 is a static field on the enum that points to HALF. The same relationship holds for each deprecated/preferred pair. Both names work identically at runtime, but new code should use the preferred names to keep intent clear.


Memory Footprint

Every element of an INDArray occupies a fixed number of bytes determined by its DataType. Understanding this is essential for planning GPU memory budgets and comparing model footprints.

DataType
Bytes per element

DOUBLE / INT64 / UINT64

8

FLOAT / INT32 / UINT32

4

FLOAT16 / BFLOAT16 / INT16 / UINT16

2

INT8 / UINT8 / BOOL

1

A 1000-element array uses 8 KB as DOUBLE, 4 KB as FLOAT, and 2 KB as FLOAT16 or BFLOAT16. For a 100M-parameter model this difference is 800 MB vs 400 MB vs 200 MB — a decisive factor in whether a model fits in GPU memory.


Migration from Beta4 and Earlier

In beta4 and all earlier releases, data type was a global, process-wide setting applied to all arrays:

In M2.1, DataBuffer.Type has been removed entirely. Each INDArray carries its own DataType, and creation methods accept it as an explicit argument. The global concept still exists as a default (see below), but it is no longer the only mechanism.

What Changed

Concept
Beta4
M2.1

Type class

DataBuffer.Type

DataType

Set global type

Nd4j.setDataType(DataBuffer.Type.X)

Nd4j.setDefaultDataTypes(DataType.X, DataType.Y)

Per-array type

Not supported

Every INDArray has a DataType

Type checking

N/A

arr.dataType()

Casting

N/A

arr.castTo(DataType.X)

Replace every DataBuffer.Type reference in your codebase:


Default Data Type

The default type for newly created arrays is FLOAT. When you call a creation method without an explicit DataType argument, ND4J uses the current default.

You can change the default at application startup with Nd4j.setDefaultDataTypes. It accepts two arguments: the default floating-point type and the default integer type.

Call setDefaultDataTypes once at startup, before any array creation. Changing it mid-run can produce inconsistent types that are hard to debug.


Creating Typed Arrays

All Nd4j creation methods accept a DataType as their first argument. Pass the type explicitly whenever you need a specific type, regardless of what the default is.

Zeros, Ones, and Value-Filled Arrays

Random Arrays

Linspace

From Java Arrays

Type inference uses the Java primitive type when creating from Java arrays. To force a specific type, create with an explicit DataType and then fill, or create and cast:


Checking the Type of an Array

Call arr.dataType() to retrieve the DataType of any INDArray:


Casting Between Types

To convert an INDArray from one DataType to another, call castTo. This always returns a new array (a copy) in the target type. The original is not modified.

Precision Loss

Casting from a higher-precision type to a lower-precision type loses information:

This is expected and intentional when using reduced precision. For training stability, keep high-precision master copies and cast only for the forward/backward pass.

Integer Truncation

Casting a floating-point array to an integer type truncates (not rounds) the fractional part:


Type Matching for Operations

In M2.1, the two operands of a binary operation must have the same DataType. If types differ, ND4J throws an exception:

This is a deliberate design choice: silent implicit promotion (as in many scripting languages) hides bugs where the user accidentally mixes types and gets unexpected precision or memory use.

Solution: cast one operand before the operation:

Choose which direction to cast based on whether you need the precision of DOUBLE or the memory savings of FLOAT.

Type-Safe Helper Pattern

When writing utility code that must accept any numeric type, check and cast defensively:


Mixed Precision Training

Mixed precision training uses lower-precision types (typically FLOAT16 or BFLOAT16) for most computation while keeping higher-precision master weights to accumulate gradients accurately. The result is significantly lower GPU memory use and higher throughput on hardware with native half-precision support (NVIDIA Volta and later, AMD RDNA2+).

Strategy

  1. Master weights are stored as FLOAT (32-bit).

  2. Before each forward pass, cast the master weights to FLOAT16 or BFLOAT16.

  3. The forward and backward passes execute in half precision.

  4. Gradients are cast back to FLOAT and accumulated into the master weights.

  5. The optimizer step runs in FLOAT.

FLOAT16 vs BFLOAT16

Both use 2 bytes per element, but they allocate those bits differently:

Type
Exponent bits
Mantissa bits
Max value

FLOAT16

5

10

~65,504

BFLOAT16

8

7

~3.4 × 10^38 (same as FLOAT)

FLOAT16 offers higher precision for values in its range, but overflows easily — activations or gradients that exceed ~65,504 become Inf. This requires loss scaling (multiplying the loss by a large constant before the backward pass) to keep gradients in range.

BFLOAT16 has the same exponent range as FLOAT, so it does not overflow under conditions that FLOAT would not overflow. Gradients stay finite without loss scaling in most cases. The trade-off is lower mantissa precision (~2 decimal digits vs ~3 for FLOAT16).

Recommendation: prefer BFLOAT16 when your hardware supports it. It requires less engineering overhead to use safely.

Setting a Default for Half-Precision Training


Reference: DataType Summary

DataType
Bytes
Floating-point?
Notes

DOUBLE

8

Yes

64-bit IEEE 754. Use for scientific computing where precision matters.

FLOAT

4

Yes

32-bit IEEE 754. Default. Good choice for most training workloads.

FLOAT16

2

Yes

16-bit half. GPU-accelerated mixed precision. Requires loss scaling. HALF is deprecated alias.

BFLOAT16

2

Yes

Brain float. Same exponent range as FLOAT. Preferred for training without loss scaling.

INT64

8

No

64-bit signed. LONG is deprecated alias.

INT32

4

No

32-bit signed. INT is deprecated alias.

INT16

2

No

16-bit signed. SHORT is deprecated alias.

INT8

1

No

8-bit signed, −128 to 127. BYTE is deprecated alias.

UINT64

8

No

64-bit unsigned.

UINT32

4

No

32-bit unsigned.

UINT16

2

No

16-bit unsigned.

UINT8

1

No

8-bit unsigned, 0 to 255. UBYTE is deprecated alias.

BOOL

1

No

Boolean. Returned by comparison ops.

UTF8

variable

No

String data. Used for label arrays.


Key API Signatures

Last updated

Was this helpful?