The Deep Learning Recommendation Model (DLRM) is a recommendation model designed to make use of both categorical and numerical inputs.
The following sections provide greater details of the dataset, running training and inference, and the training results.
Scripts and sample code
These are the important modules in this repository:
main.py- The main entrypoint script for training, evaluating, and benchmarking.model.py- Defines the DLRM model and some auxiliary functions used to train it.dataloader.py- Handles defining the dataset objects based on command-line flags.datasets.py- Defines theTfRawBinaryDatasetclass responsible for storing and loading the training data.slurm_multinode.sh- Example batch script for multi-node training on SLURM clusters.lr_scheduler.py- Defines a TensorFlow learning rate scheduler that supports both learning rate warmup and polynomial decay.embedding.py- Implementations of the embedding layers.interaction.py- Implementation of the dot-interaction layer using TensorFlow operations.tensorflow-dot-based-interact- A directory with a set of custom CUDA kernels. They provide fast implementations of the dot-interaction operation for various precisions and hardware platforms.utils.py- General utilities, such as a timer used for taking performance measurements.
Parameters
The table below lists the most important command-line parameters of the main.py script.
| Scope | parameter | Comment | Default Value |
|---|---|---|---|
| datasets | dataset_path | Path to the JSON file with the sizes of embedding tables | |
| function | mode | Choose "train" to train the model, "inference" to benchmark inference and "eval" to run validation | train |
| optimizations | amp | Enable automatic mixed precision | False |
| optimizations | xla | Enable XLA | False |
| hyperparameters | batch_size | Batch size used for training | 65536 |
| hyperparameters | epochs | Number of epochs to train for | 1 |
| hyperparameters | optimizer | Optimization algorithm for training | SGD |
| hyperparameters | evals_per_epoch | Number of evaluations per epoch | 1 |
| hyperparameters | valid_batch_size | Batch size used for validation | 65536 |
| hyperparameters | max_steps | Stop the training/inference after this many optimization steps | -1 |
| checkpointing | restore_checkpoint_path | Path from which to restore a checkpoint before training | None |
| checkpointing | save_checkpoint_path | Path to which to save a checkpoint file at the end of the training | None |
| debugging | run_eagerly | Disable all tf.function decorators for debugging | False |
| debugging | print_freq | Number of steps between debug prints | 1000 |
Command-line options
The main.py script supports a number of command-line flags. You can get the descriptions of those by running python main.py --help.
Getting the data
This example uses the Criteo Terabyte Dataset. The first 23 days are used as the training set. The last day is split in half. The first part is used as a validation set and the second set is used as a hold-out test set.
Dataset guidelines
The preprocessing steps applied to the raw data include:
- Replacing the missing values with
0. - Replacing the categorical values that exist fewer than 15 times with a special value.
- Converting the hash values to consecutive integers.
- Adding 2 to all the numerical features so that all of them are greater or equal to 1.
- Taking a natural logarithm of all numerical features.
BYO dataset
This implementation supports using other datasets thanks to BYO dataset functionality. The BYO dataset functionality allows users to plug in their dataset in a common fashion for all Recommender models that support this functionality. Using BYO dataset functionality, the user does not have to modify the source code of the model thanks to the Feature Specification file. For general information on how BYO dataset works, refer to the BYO dataset overview section.
There are three ways to plug in user's dataset:
1. Provide an unprocessed dataset in a format matching the one used by Criteo 1TB, then use Criteo 1TB's preprocessing. Feature Specification file is then generated automatically.
The required format of the user's dataset is:The data should be split into text files. Each line of those text files should contain a single training example. An example should consist of multiple fields separated by tabulators:
- The first field is the label – 1 for a positive example and 0 for negative.
- The next N tokens should contain the numerical features separated by tabs.
- The next M tokens should contain the hashed categorical features separated by tabs.
The correct dataset files together with the Feature Specification yaml file will be generated automatically by preprocessing script.
For an example of using this process, refer to the Quick Start Guide
2. Provide a CSV containing preprocessed data and a simplified Feature Specification yaml file, then transcode the data with `transcode.py` script
This option should be used if the user has their own CSV file with a preprocessed dataset they want to train on.The required format of the user's dataset is:
- CSV files containing the data, already split into train and test sets.
- Feature Specification yaml file describing the layout of the CSV data
For an example of a feature specification file, refer to the tests/transcoding folder.
The CSV containing the data:
- should be already split into train and test
- should contain no header
- should contain one column per feature, in the order specified by the list of features for that chunk in the source_spec section of the feature specification file
- categorical features should be non-negative integers in the range [0,cardinality-1] if cardinality is specified
The Feature Specification yaml file:
- needs to describe the layout of data in CSV files
- may contain information about cardinalities. However, if set to
auto, they will be inferred from the data by the transcoding script.
Refer to tests/transcoding/small_csv.yaml for an example of the yaml Feature Specification.
The following example shows how to use this way of plugging user's dataset:
Prepare your data and save the path:
DATASET_PARENT_DIRECTORY=/raid/dlrm
Build the DLRM image with:
docker build -t nvidia_dlrm_tf .
Launch the container with:
docker run --cap-add SYS_NICE --runtime=nvidia -it --rm --ipc=host -v ${DATASET_PARENT_DIRECTORY}/data:/data nvidia_dlrm_tf bash
If you are just testing the process, you can create synthetic csv data:
python gen_csv.py --feature_spec_in tests/transcoding/small_csv.yaml
Convert the data:
mkdir /data/conversion_output
cp tests/transcoding/small_csv.yaml /data/feature_spec.yaml
python transcode.py --input /data --output /data/converted
You may need to tune the --chunk_size parameter. Higher values speed up the conversion but require more RAM.
This will convert the data from /data and save the output in /data/converted.
A feature specification file describing the new data will be automatically generated.
To run the training on 1 GPU:
horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla
- multi-GPU for DGX A100:
horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla
- multi-GPU for DGX-1 and DGX-2:
horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla
3. Provide a fully preprocessed dataset, saved in split binary files, and a Feature Specification yaml file
This is the option to choose if you want full control over preprocessing and/or want to preprocess data directly to the target format.Your final output will need to contain a Feature Specification yaml describing data and file layout.
For an example feature specification file, refer to tests/feature_specs/criteo_f15.yaml
For details, refer to the BYO dataset overview section.
Channel definitions and requirements
This model defines three channels:
- categorical, accepting an arbitrary number of features
- numerical, accepting an arbitrary number of features
- label, accepting a single feature
The training script expects two mappings:
- train
- test
For performance reasons:
- The only supported dataset type is split binary
- Splitting chunks into multiple files is not supported.
- Each categorical feature has to be provided in a separate chunk
- All numerical features have to be provided in a single chunk
- All numerical features have to appear in the same order in channel_spec and source_spec
- Only integer types are supported for categorical features
- Only float16 is supported for numerical features
BYO dataset constraints for the model
There are the following constraints of BYO dataset functionality for this model:
- The performance of the model depends on the dataset size. Generally, the model should scale better for datasets containing more data points. For a smaller dataset, you might experience slower performance than the one reported for Criteo
- Using other datasets might require tuning some hyperparameters (for example, learning rate, beta1 and beta2) to reach desired accuracy.
- The optimized cuda interaction kernels for FP16 and TF32 assume that the number of categorical variables is smaller than WARP_SIZE=32 and embedding size is <=128
Preprocess with Spark
The preprocessing scripts provided in this repository support running both on CPU and on DGX-2 using Apache Spark 3.0.
It should be possible to change the values in preproc/dgx2_config.sh
so that they'll work on other hardware platforms such as DGX-1.
Note that the preprocessing will require about 4TB of disk storage.
The syntax for the preprocessing script is as follows:
cd preproc
./prepare_dataset.sh <DGX2|CPU> <frequency_threshold>
The first argument is the hardware platform to use (either DGX-2 or pure-CPU). The second argument means the frequency
threshold to apply to the categorical variables. For a frequency threshold T, the categorical values that occur less
often than T will be replaced with a special embedding. Thus, a larger value of T will require smaller embedding tables
and will substantially reduce the overall size of the model.
For the Criteo Terabyte dataset we recommend a frequency threshold of T=3 if you intend to run the hybrid-parallel mode
on multiple GPUs. If you want to make the model fit into a single NVIDIA Tesla V100-32GB, you can set T=15.
The preprocessing scripts makes use of the following environment variables to configure the data directory paths:
download_dir– this directory should contain the original Criteo Terabyte CSV filesspark_output_path– directory to which the parquet data will be writtenconversion_intermediate_dir– directory used for storing intermediate data used to convert from parquet to train-ready formatfinal_output_dir– directory to store the final results of the preprocessing which can then be used to train DLRM
The script spark_data_utils.py is a PySpark application, which is used to preprocess the Criteo Terabyte Dataset. In the Docker image, we have installed Spark 3.0.1, which will start a standalone cluster of Spark. The scripts run_spark_cpu.sh and run_spark_gpu.sh start Spark, then runs several PySpark jobs with spark_data_utils.py, for example:
generates the dictionary
-
transforms the train dataset
-
transforms the test dataset
-
transforms the validation dataset
Change the variables in the
run-spark.shscript according to your environment. Configure the paths.
export SPARK_LOCAL_DIRS=/data/spark-tmp
export INPUT_PATH=/data/criteo
export OUTPUT_PATH=/data/output
Note that the Spark job requires about 3TB disk space used for data shuffle.
Where:
SPARK_LOCAL_DIRS is the path where Spark uses to write shuffle data.
INPUT_PATH is the path of the Criteo Terabyte Dataset, including uncompressed files like day_0, day_1…
OUTPUT_PATH is where the script writes the output data. It will generate the following subdirectories of models, train, test, and validation.
- The
modelis the dictionary folder. - The
trainis the train dataset transformed from day_0 to day_22. - The
testis the test dataset transformed from the prior half of day_23. - The
validationis the dataset transformed from the latter half of day_23.
Configure the resources which Spark will use.
export TOTAL_CORES=80
export TOTAL_MEMORY=800
Where:
TOTAL_CORES is the total CPU cores you want Spark to use.
TOTAL_MEMORY is the total memory Spark will use.
Configure frequency limit.
USE_FREQUENCY_LIMIT=15
The frequency limit is used to filter out the categorical values which appear less than n times in the whole dataset, and make them be 0. Change this variable to 1 to enable it. The default frequency limit is 15 in the script. You also can change the number as you want by changing the line of OPTS="--frequency_limit 8".
Training process
The main training script resides in main.py. The speed of training is measured by throughput i.e., the number
of samples processed per second. We use mixed precision training with static loss scaling for the bottom and top MLPs while embedding tables are stored in FP32 format.