text:
# ResNet-50 v1.5 for TensorFlow

This repository provides a script and recipe to train the ResNet-50 v1.5 model to achieve state-of-the-art accuracy, and is tested and maintained by NVIDIA.
ResNet-50 model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider PyTorch or TensorFlow2 models as a substitute for your requirements.

## Table Of Contents
* [Model overview](#model-overview)
    * [Default configuration](#default-configuration)
        * [Optimizer](#optimizer)
        * [Data augmentation](#data-augmentation)
    * [Feature support matrix](#feature-support-matrix)
        * [Features](#features)
    * [Mixed precision training](#mixed-precision-training)
        * [Enabling mixed precision](#enabling-mixed-precision)
        * [Enabling TF32](#enabling-tf32)
* [Setup](#setup)
    * [Requirements](#requirements)
* [Quick Start Guide](#quick-start-guide)
* [Advanced](#advanced)
    * [Scripts and sample code](#scripts-and-sample-code)
    * [Parameters](#parameters)
        * [The `main.py` script](#the-mainpy-script)
    * [Quantization Aware training](#quantization-aware-training)
        * [Post process checkpoint](#post-process-checkpoint)
        * [Exporting Frozen graphs](#exporting-frozen-graphs)
    * [Inference process](#inference-process)
* [Performance](#performance)
    * [Benchmarking](#benchmarking)
        * [Training performance benchmark](#training-performance-benchmark)
        * [Inference performance benchmark](#inference-performance-benchmark)
    * [Results](#results)
        * [Training accuracy results](#training-accuracy-results)
            * [Training accuracy: NVIDIA DGX A100 (8x A100 40GB)](#training-accuracy-nvidia-dgx-a100-8x-a100-40gb)
            * [Training accuracy: NVIDIA DGX-1 (8x V100 16G)](#training-accuracy-nvidia-dgx-1-8x-v100-16g)
        * [Training performance results](#training-performance-results)
            * [Training performance: NVIDIA DGX A100 (8x A100 40GB)](#training-performance-nvidia-dgx-a100-8x-a100-40gb)
            * [Training performance: NVIDIA DGX-1 (8x V100 16G)](#training-performance-nvidia-dgx-1-8x-v100-16g)
            * [Training performance: NVIDIA DGX-2 (16x V100 32G)](#training-performance-nvidia-dgx-2-16x-v100-32g)
        * [Training time for 90 Epochs](#training-time-for-90-epochs)
            * [Training time: NVIDIA DGX A100 (8x A100 40G)](#training-time-nvidia-dgx-a100-8x-a100-40gb)
            * [Training time: NVIDIA DGX-1 (8x V100 16G)](#training-time-nvidia-dgx-1-8x-v100-16g)
            * [Training time: NVIDIA DGX-2 (16x V100 32G)](#training-time-nvidia-dgx-2-16x-v100-32g)
        * [Inference performance results](#inference-performance-results)
            * [Inference performance: NVIDIA DGX A100 (1x A100 40GB)](#inference-performance-nvidia-dgx-a100-1x-a100-40gb)
            * [Inference performance: NVIDIA DGX-1 (1x V100 16G)](#inference-performance-nvidia-dgx-1-1x-v100-16g)
            * [Inference performance: NVIDIA DGX-2 (1x V100 32G)](#inference-performance-nvidia-dgx-2-1x-v100-32g)
            * [Inference performance: NVIDIA T4 (1x T4 16G)](#inference-performance-nvidia-t4-1x-t4-16g)
* [Release notes](#release-notes)
    * [Changelog](#changelog)
    * [Known issues](#known-issues)

## Model overview
The ResNet50 v1.5 model is a modified version of the [original ResNet50 v1 model](https://arxiv.org/abs/1512.03385).

The difference between v1 and v1.5 is in the bottleneck blocks which requires
downsampling, for example, v1 has stride = 2 in the first 1x1 convolution, whereas v1.5 has stride = 2 in the 3x3 convolution.

This difference makes ResNet50 v1.5 slightly more accurate (~0.5% top1) than v1,
but comes with a small performance drawback (~5% imgs/sec).

The following performance optimizations were implemented in this model:
* JIT graph compilation with [XLA](https://www.tensorflow.org/xla)
* Multi-GPU training with [Horovod](https://github.com/horovod/horovod)
* Automated mixed precision [AMP](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html)

This model is trained with mixed precision using Tensor Cores on Volta, Turing, and the NVIDIA Ampere GPU architectures. Therefore, researchers can get results 3x faster than training without Tensor Cores, while experiencing the benefits of mixed precision training. This model is tested against each NGC monthly container release to ensure consistent accuracy and performance over time.

### Default configuration

The following sections highlight the default configuration for the ResNet50 model.

#### Optimizer

This model uses the SGD optimizer with the following hyperparameters:

* Momentum (0.875).
* Learning rate (LR) = 0.256 for 256 batch size, for other batch sizes we linearly scale the learning
  rate.
* Learning rate schedule - we use cosine LR schedule.
* For bigger batch sizes (512 and up) we use linear warmup of the learning rate.
during the first 5 epochs according to [Training ImageNet in 1 hour](https://arxiv.org/abs/1706.02677).
* Weight decay: 3.0517578125e-05 (1/32768).
* We do not apply Weight decay on batch norm trainable parameters (gamma/bias).
* Label Smoothing: 0.1.
* We train for:
    * 90 Epochs -> 90 epochs is a standard for ResNet family networks.
    * 250 Epochs -> best possible accuracy.
* For 250 epoch training we also use [MixUp regularization](https://arxiv.org/pdf/1710.09412.pdf).

#### Data Augmentation

This model uses the following data augmentation:

* For training:
  * Normalization.
  * Random resized crop to 224x224.
    * Scale from 8% to 100%.
    * Aspect ratio from 3/4 to 4/3.
  * Random horizontal flip.
* For inference:
  * Normalization.
  * Scale to 256x256.
  * Center crop to 224x224.

### Feature support matrix

The following features are supported by this model.

| Feature               | ResNet-50 v1.5 Tensorflow             |
|-----------------------|--------------------------
|Multi-GPU training with [Horovod](https://github.com/horovod/horovod)  |  Yes |
|[NVIDIA DALI](https://docs.nvidia.com/deeplearning/dali/release-notes/index.html)                |  Yes |
|Automatic mixed precision (AMP) | Yes |

#### Features

Multi-GPU training with Horovod - Our model uses Horovod to implement efficient multi-GPU training with NCCL.
For details, refer to the example sources in this repository or the [TensorFlow tutorial](https://github.com/horovod/horovod/#usage).

NVIDIA DALI - DALI is a library accelerating data preparation pipeline. To accelerate your input pipeline, you only need to define your data loader
with the DALI library. For details, refer to the example sources in this repository or the [DALI documentation](https://docs.nvidia.com/deeplearning/dali/index.html).

Automatic mixed precision (AMP) - Computation graph can be modified by TensorFlow on runtime to support mixed precision training.
Detailed explanation of mixed precision can be found in the next section.

### Mixed precision training
Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in Volta, and following with both the Turing and Ampere architectures, significant training speedups are experienced by switching to mixed precision -- up to 3x overall speedup on the most arithmetically intense model architectures. Using [mixed precision training](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) previously required two steps:

1.  Porting the model to use the FP16 data type where appropriate.
2.  Adding loss scaling to preserve small gradient values.

This can now be achieved using Automatic Mixed Precision (AMP) for TensorFlow to enable the full [mixed precision methodology](https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/index.html#tensorflow) in your existing TensorFlow model code.  AMP enables mixed precision training on Volta and Turing GPUs automatically. The TensorFlow framework code makes all necessary model changes internally.

In TF-AMP, the computational graph is optimized to use as few casts as necessary and maximize the use of FP16, and the loss scaling is automatically applied inside of supported optimizers. AMP can be configured to work with the existing tf.contrib loss scaling manager by disabling the AMP scaling with a single environment variable to perform only the automatic mixed-precision optimization. It accomplishes this by automatically rewriting all computation graphs with the necessary operations to enable mixed precision training and automatic loss scaling.

For information about:
-   How to train using mixed precision, see the [Mixed Precision Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed Precision](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) documentation.
-   Techniques used for mixed precision training, see the [Mixed-Precision Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog.
-   How to access and enable AMP for TensorFlow, see [Using TF-AMP](https://docs.nvidia.com/deeplearning/dgx/tensorflow-user-guide/index.html#tfamp) from the TensorFlow User Guide.

#### Enabling mixed precision

Mixed precision is enabled in TensorFlow by using the Automatic Mixed Precision (TF-AMP) extension which casts variables to half-precision upon retrieval, while storing variables in single-precision format. Furthermore, to preserve small gradient magnitudes in backpropagation, a [loss scaling](https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/index.html#lossscaling) step must be included when applying gradients. In TensorFlow, loss scaling can be applied statically by using simple multiplication of loss by a constant value or automatically, by TF-AMP. Automatic mixed precision makes all the adjustments internally in TensorFlow, providing two benefits over manual operations. First, programmers need not modify network model code, reducing development and maintenance effort. Second, using AMP maintains forward and backward compatibility with all the APIs for defining and running TensorFlow models.

To enable mixed precision, you can simply add the values to the environmental variables inside your training script:
- Enable TF-AMP graph rewrite:
  ```
  os.environ["TF_ENABLE_AUTO_MIXED_PRECISION_GRAPH_REWRITE"] = "1"
  ```

- Enable Automated Mixed Precision:
  ```
  os.environ['TF_ENABLE_AUTO_MIXED_PRECISION'] = '1'

  ```

#### Enabling TF32

TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on Volta GPUs.

TF32 Tensor Cores can speed up networks using FP32, typically with no loss of accuracy. It is more robust than FP16 for models which require high dynamic range for weights or activations.

For more information, refer to the [TensorFloat-32 in the A100 GPU Accelerates AI Training, HPC up to 20x](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) blog post.

TF32 is supported in the NVIDIA Ampere GPU architecture and is enabled by default.

## Setup

The following section lists the requirements that you need to meet in order to use the ResNet50 v1.5 model.

### Requirements
This repository contains Dockerfile which extends the TensorFlow NGC container and encapsulates all dependencies.  Aside from these dependencies, ensure you have the following software:

- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker)
- [TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow)
- GPU-based architecture:
  - [NVIDIA Volta](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/)
  - [NVIDIA Turing](https://www.nvidia.com/en-us/geforce/turing/)
  - [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/)

For more information about how to get started with NGC containers, see the
following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation:
* [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html),
* [Accessing And Pulling From The NGC container registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry),
* [Running TensorFlow](https://docs.nvidia.com/deeplearning/frameworks/tensorflow-release-notes/running.html#running).

For those unable to use the [TensorFlow NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow) to set up the required environment or create your own container, see the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html).

## Quick Start Guide
To train your model using mixed precision or TF32 with Tensor Cores or FP32, perform the following steps using the default parameters of the ResNet-50 v1.5 model on the [ImageNet](http://www.image-net.org/) dataset. For the specifics concerning training and inference, see the [Advanced](#advanced) section.

1. Clone the repository.
```
git clone https://github.com/NVIDIA/DeepLearningExamples
cd DeepLearningExamples/TensorFlow/Classification/ConvNets
```

2. Download and preprocess the dataset.
The ResNet50 v1.5 script operates on ImageNet 1k, a widely popular image classification dataset from the ILSVRC challenge.

* [Download the images](http://image-net.org/download-images)
* Extract the training and validation data:
```bash
mkdir train && mv ILSVRC2012_img_train.tar train/ && cd train
tar -xvf ILSVRC2012_img_train.tar && rm -f ILSVRC2012_img_train.tar
find . -name "*.tar" | while read NAME ; do mkdir -p "${NAME%.tar}"; tar -xvf "${NAME}" -C "${NAME%.tar}"; rm -f "${NAME}"; done
cd ..
mkdir val && mv ILSVRC2012_img_val.tar val/ && cd val && tar -xvf ILSVRC2012_img_val.tar
```
* Preprocess dataset to TFRecord form using [script](https://github.com/tensorflow/models/blob/archive/research/inception/inception/data/build_imagenet_data.py). Additional metadata from [autors repository](https://github.com/tensorflow/models/tree/archive/research/inception/inception/data) might be required.

3. Build the ResNet-50 v1.5 TensorFlow NGC container.
```bash
docker build . -t nvidia_rn50
```

4. Start an interactive session in the NGC container to run training/inference.
After you build the container image, you can start an interactive CLI session with
```bash
nvidia-docker run --rm -it -v <path to imagenet>:/data/tfrecords --ipc=host nvidia_rn50
```

5. (Optional) Create index files to use DALI.
To allow proper sharding in a multi-GPU environment, DALI has to create index files for the dataset. To create index files, run inside the container:
```bash
bash ./utils/dali_index.sh /data/tfrecords <index file store location>
```
Index files can be created once and then reused. It is highly recommended to save them into a persistent location.

6. Start training.
To run training for a standard configuration (as described in [Default
configuration](#default-configuration), DGX1V, DGX2V, single GPU, FP16, FP32, 50, 90, and 250 epochs), run
one of the scripts int the `resnet50v1.5/training` directory. Ensure ImageNet is mounted in the
`/data/tfrecords` directory.

For example, to train on DGX-1 for 90 epochs using AMP, run:

`bash ./resnet50v1.5/training/DGX1_RN50_AMP_90E.sh /path/to/result /data`

Additionally, features like DALI data preprocessing or TensorFlow XLA can be enabled with
following arguments when running those scripts:

`bash ./resnet50v1.5/training/DGX1_RN50_AMP_90E.sh /path/to/result /data --xla --dali`

7. Start validation/evaluation.
To evaluate the validation dataset located in `/data/tfrecords`, run `main.py` with
`--mode=evaluate`. For example:

`python main.py --mode=evaluate --data_dir=/data/tfrecords --batch_size <batch size> --model_dir
<model location> --results_dir <output location> [--xla] [--amp]`

The optional `--xla` and `--amp` flags control XLA and AMP during evaluation.

## Advanced

The following sections provide greater details of the dataset, running training and inference, and the training results.

### Scripts and sample code

In the root directory, the most important files are:
 - `main.py`:               the script that controls the logic of training and validation of the ResNet-like models
 - `Dockerfile`:            Instructions for Docker to build a container with the basic set of dependencies to run ResNet like models for image classification
 - `requirements.txt`:      a set of extra Python requirements for running ResNet-like models

The `model/` directory contains the following modules used to define ResNet family models:
 - `resnet.py`: the definition of ResNet, ResNext, and SE-ResNext model
 - `blocks/conv2d_block.py`: the definition of 2D convolution block
 - `blocks/resnet_bottleneck_block.py`: the definition of ResNet-like bottleneck block
 - `layers/*.py`: definitions of specific layers used in the ResNet-like model

The `utils/` directory contains the following utility modules:
 - `cmdline_helper.py`: helper module for command line processing
 - `data_utils.py`: module defining input data pipelines
 - `dali_utils.py`: helper module for DALI
 - `image_processing.py`: image processing and data augmentation functions
 - `learning_rate.py`: definition of used learning rate schedule
 - `optimizers.py`: definition of used custom optimizers
 - `hooks/*.py`: definitions of specific hooks allowing logging of training and inference process

The `runtime/` directory contains the following module that define the mechanics of the training process:
 - `runner.py`: module encapsulating the training, inference and evaluation

### Parameters

#### The `main.py` script
The script for training and evaluating the ResNet-50 v1.5 model has a variety of parameters that control these processes.

```
usage: main.py [-h] [--arch {resnet50,resnext101-32x4d,se-resnext101-32x4d}]
               [--mode {train,train_and_evaluate,evaluate,predict,training_benchmark,inference_benchmark}]
               [--export_dir EXPORT_DIR] [--to_predict TO_PREDICT]
               --batch_size BATCH_SIZE [--num_iter NUM_ITER]
               [--run_iter RUN_ITER] [--iter_unit {epoch,batch}]
               [--warmup_steps WARMUP_STEPS] [--model_dir MODEL_DIR]
               [--results_dir RESULTS_DIR] [--log_filename LOG_FILENAME]
               [--display_every DISPLAY_EVERY] [--seed SEED]
               [--gpu_memory_fraction GPU_MEMORY_FRACTION] [--gpu_id GPU_ID]
               [--finetune_checkpoint FINETUNE_CHECKPOINT] [--use_final_conv]
               [--quant_delay QUANT_DELAY] [--quantize] [--use_qdq]
               [--symmetric] [--data_dir DATA_DIR]
               [--data_idx_dir DATA_IDX_DIR] [--dali]
               [--synthetic_data_size SYNTHETIC_DATA_SIZE] [--lr_init LR_INIT]
               [--lr_warmup_epochs LR_WARMUP_EPOCHS]
               [--weight_decay WEIGHT_DECAY] [--weight_init {fan_in,fan_out}]
               [--momentum MOMENTUM] [--label_smoothing LABEL_SMOOTHING]
               [--mixup MIXUP] [--cosine_lr] [--xla]
               [--data_format {NHWC,NCHW}] [--amp]
               [--static_loss_scale STATIC_LOSS_SCALE]

JoC-RN50v1.5-TF

optional arguments:
  -h, --help            show this help message and exit.
  --arch {resnet50,resnext101-32x4d,se-resnext101-32x4d}
                        Architecture of model to run.
  --mode {train,train_and_evaluate,evaluate,predict,training_benchmark,inference_benchmark}
                        The execution mode of the script.
  --export_dir EXPORT_DIR
                        Directory in which to write exported SavedModel.
  --to_predict TO_PREDICT
                        Path to file or directory of files to run prediction
                        on.
  --batch_size BATCH_SIZE
                        Size of each minibatch per GPU.
  --num_iter NUM_ITER   Number of iterations to run.
  --run_iter RUN_ITER   Number of training iterations to run on single run.
  --iter_unit {epoch,batch}
                        Unit of iterations.
  --warmup_steps WARMUP_STEPS
                        Number of steps considered as warmup and not taken
                        into account for performance measurements.
  --model_dir MODEL_DIR
                        Directory in which to write model. If undefined,
                        results dir will be used.
  --results_dir RESULTS_DIR
                        Directory in which to write training logs, summaries
                        and checkpoints.
  --log_filename LOG_FILENAME
                        Name of the JSON file to which write the training log.
  --display_every DISPLAY_EVERY
                        How often (in batches) to print out running
                        information.
  --seed SEED           Random seed.
  --gpu_memory_fraction GPU_MEMORY_FRACTION
                        Limit memory fraction used by training script for DALI.
  --gpu_id GPU_ID       Specify ID of the target GPU on multi-device platform.
                        Effective only for single-GPU mode.
  --finetune_checkpoint FINETUNE_CHECKPOINT
                        Path to pre-trained checkpoint which will be used for
                        fine-tuning.
  --use_final_conv      Use convolution operator instead of MLP as last layer.
  --quant_delay QUANT_DELAY
                        Number of steps to be run before quantization starts
                        to happen.
  --quantize            Quantize weights and activations during training.
                        (Defaults to Assymmetric quantization)
  --use_qdq             Use QDQV3 op instead of FakeQuantWithMinMaxVars op for
                        quantization. QDQv3 does only scaling.
  --symmetric           Quantize weights and activations during training using
                        symmetric quantization.

Dataset arguments:
  --data_dir DATA_DIR   Path to dataset in TFRecord format. Files should be
                        named 'train-*' and 'validation-*'.
  --data_idx_dir DATA_IDX_DIR
                        Path to index files for DALI. Files should be named
                        'train-*' and 'validation-*'.
  --dali                Enable DALI data input.
  --synthetic_data_size SYNTHETIC_DATA_SIZE
                        Dimension of image for synthetic dataset.

Training arguments:
  --lr_init LR_INIT     Initial value for the learning rate.
  --lr_warmup_epochs LR_WARMUP_EPOCHS
                        Number of warmup epochs for learning rate schedule.
  --weight_decay WEIGHT_DECAY
                        Weight Decay scale factor.
  --weight_init {fan_in,fan_out}
                        Model weight initialization method.
  --momentum MOMENTUM   SGD momentum value for the Momentum optimizer.
  --label_smoothing LABEL_SMOOTHING
                        The value of label smoothing.
  --mixup MIXUP         The alpha parameter for mixup (if 0 then mixup is not
                        applied).
  --cosine_lr           Use cosine learning rate schedule.

Generic optimization arguments:
  --xla                 Enable XLA (Accelerated Linear Algebra) computation
                        for improved performance.
  --data_format {NHWC,NCHW}
                        Data format used to do calculations.
  --amp                 Enable Automatic Mixed Precision to speedup
                        computation using tensor cores.

Automatic Mixed Precision arguments:
  --static_loss_scale STATIC_LOSS_SCALE
                        Use static loss scaling in FP32 AMP.

```

### Quantization Aware Training
Quantization Aware training (QAT) simulates quantization during training by quantizing weights and activation layers. This will help reduce the loss in accuracy when we convert the network
trained in FP32 to INT8 for faster inference. QAT introduces additional nodes in the graph which will be used to learn the dynamic ranges of weights and activation layers. Tensorflow provides
a <a href="https://www.tensorflow.org/versions/r1.14/api_docs/python/tf/contrib/quantize">quantization tool</a> which automatically adds these nodes in-place. Typical workflow
for training QAT networks is to train a model until convergence and then finetune with the quantization layers. It is recommended that QAT is performed on a single GPU.

* For 1 GPU
    * Command: `sh resnet50v1.5/training/GPU1_RN50_QAT.sh <path to pre-trained ckpt dir> <path to dataset directory> <result_directory>`

It is recommended to finetune a model with quantization nodes rather than train a QAT model from scratch. The latter can also be performed by setting `quant_delay` parameter.
`quant_delay` is the number of steps after which quantization nodes are added for QAT. If we are fine-tuning, `quant_delay` is set to 0.

For QAT network, we use <a href="https://www.tensorflow.org/versions/r1.15/api_docs/python/tf/quantization/quantize_and_dequantize">tf.quantization.quantize_and_dequantize operation</a>.
These operations are automatically added at weights and activation layers in the RN50 by using `tf.contrib.quantize.experimental_create_training_graph` utility. Support for using `tf.quantization.quantize_and_dequantize`
operations for `tf.contrib.quantize.experimental_create_training_graph` has been added in <a href="https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow">TensorFlow 20.01-py3 NGC container</a> and later versions, which is required for this task.

#### Post process checkpoint
  `postprocess_ckpt.py` is a utility to convert the final classification FC layer into a 1x1 convolution layer using the same weights. This is required to ensure TensorRT can parse QAT models successfully.
  This script should be used after performing QAT to reshape the FC layer weights in the final checkpoint.
  Arguments:
     * `--input` : Path to the trained checkpoint of RN50.
     * `--output` : Name of the new checkpoint file which has the FC layer weights reshaped into 1x1 conv layer weights.
     * `--dense_layer` : Name of the FC layer

#### Exporting Frozen graphs
To export frozen graphs (which can be used for inference with <a href="https://developer.nvidia.com/tensorrt">TensorRT</a>), use:

`python export_frozen_graph.py --checkpoint <path_to_checkpoint> --quantize --use_final_conv --use_qdq --symmetric --input_format NCHW --compute_format NCHW --output_file=<output_file_name>`

Arguments:

* `--checkpoint` : Optional argument to export the model with checkpoint weights.
* `--quantize` : Optional flag to export quantized graphs.
* `--use_qdq` : Use quantize_and_dequantize (QDQ) op instead of FakeQuantWithMinMaxVars op for quantization. QDQ does only scaling.
* `--input_format` : Data format of input tensor (Default: NCHW). Use NCHW format to optimize the graph with TensorRT.
* `--compute_format` : Data format of the operations in the network (Default: NCHW). Use NCHW format to optimize the graph with TensorRT.

### Inference process
To run inference on a single example with a checkpoint and a model script, use:

`python main.py --mode predict --model_dir <path to model> --to_predict <path to image> --results_dir <path to results>`

The optional `--xla` and `--amp` flags control XLA and AMP during inference. To run inference using TF-TRT, please use the following command:

`python inference.py --model <path to model> --tf-trt --batch-size <inference_batch_size> --data-dir <path to data>`

The optional `--amp` flag controls AMP during inference.

## Performance

The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to [NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference).

### Benchmarking

The following section shows how to run benchmarks measuring the model performance in training and inference modes.

#### Training performance benchmark

To benchmark the training performance on a specific batch size, run:

* For 1 GPU
    * FP32 / TF32

        `python ./main.py --mode=training_benchmark --warmup_steps 200 --batch_size <batch size> --data_dir=<path to imagenet> --results_dir=<path to results directory>`

    * AMP

        `python ./main.py --mode=training_benchmark  --amp --warmup_steps 200 --batch_size <batch size> --data_dir=<path to imagenet> --results_dir=<path to results directory>`

* For multiple GPUs
    * FP32 / TF32

        `mpiexec --allow-run-as-root --bind-to socket -np <num_gpus> python ./main.py --mode=training_benchmark --batch_size <batch size> --data_dir=<path to imagenet> --results_dir=<path to results directory>`

    * AMP

        `mpiexec --allow-run-as-root --bind-to socket -np <num_gpus> python ./main.py --mode=training_benchmark --amp --batch_size <batch size> --data_dir=<path to imagenet> --results_dir=<path to results directory>`

Each of these scripts runs 200 warm-up iterations and measures the first epoch.

To control warmup and benchmark length, use the `--warmup_steps`, `--num_iter` and `--iter_unit` flags. Features like XLA or DALI can be controlled
with `--xla` and `--dali` flags. For proper throughput reporting the value of `--num_iter` must be greater than `--warmup_steps` value.
Suggested batch sizes for training are 256 for mixed precision training and 128 for single precision training per single V100 16 GB.

If no `--data_dir=<path to imagenet>` flag is specified then the benchmarks will use a synthetic dataset. The resolution of synthetic images used can be controlled with `--synthetic_data_size` flag.

#### Inference performance benchmark

To benchmark the inference performance on a specific batch size, run:

* FP32 / TF32

`python ./main.py --mode=inference_benchmark --warmup_steps 20 --num_iter 100 --iter_unit batch --batch_size <batch size> --data_dir=<path to imagenet> --results_dir=<path to results directory>`

* AMP

`python ./main.py --mode=inference_benchmark --amp --warmup_steps 20 --num_iter 100 --iter_unit batch --batch_size <batch size> --data_dir=<path to imagenet> --results_dir=<path to results directory>`

By default, each of these scripts runs 20 warm-up iterations and measures the next 80 iterations.
To control warm-up and benchmark length, use the `--warmup_steps`, `--num_iter` and `--iter_unit` flags.
If no `--data_dir=<path to imagenet>` flag is specified then the benchmarks will use a synthetic dataset.

The benchmark can be automated with the `inference_benchmark.sh` script provided in `resnet50v1.5`, by simply running:
`bash ./resnet50v1.5/inference_benchmark.sh <data dir> <data idx dir>`

The `<data dir>` parameter refers to the input data directory (by default `/data/tfrecords` inside the container).
By default, the benchmark tests the following configurations: **FP32**, **AMP**, **AMP + XLA** with different batch sizes.
When the optional directory with the DALI index files `<data idx dir>` is specified, the benchmark executes an additional **DALI + AMP + XLA** configuration.
For proper throughput reporting the value of `--num_iter` must be greater than `--warmup_steps` value.

For performance benchmark of raw model, synthetic dataset can be used. To use synthetic dataset, use `--synthetic_data_size` flag instead of `--data_dir` to specify input image size.

### Results

The following sections provide details on how we achieved our performance and accuracy in training and inference.

#### Training accuracy results

##### Training accuracy: NVIDIA DGX A100 (8x A100 40GB)

Our results were obtained by running the `/resnet50v1.5/training/DGXA100_RN50_{PRECISION}_90E.sh`
training script in the [TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow)
NGC container on NVIDIA DGX A100 (8x A100 40GB) GPUs.

| Epochs | Batch Size / GPU | Accuracy - TF32 (top1) | Accuracy - mixed precision (top1) |
|--------|------------------|-----------------|----------------------------|
| 90     | 256              | 77.01           | 76.93                      |

##### Training accuracy: NVIDIA DGX-1 (8x V100 16G)
Our results were obtained by running the `/resnet50v1.5/training/DGX1_RN50_{PRECISION}_{EPOCHS}E.sh`
training script in the [TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow)
NGC container on NVIDIA DGX-1 with (8x V100 16G) GPUs.

| Epochs | Batch Size / GPU | Accuracy - FP32 | Accuracy - mixed precision |
|--------|------------------|-----------------|----------------------------|
| 90   | 128 (FP32) / 256 (AMP) | 77.01             | 76.99   |
| 250  | 128 (FP32) / 256 (AMP) | 78.34             | 78.35   |

**Example training loss plot**

![TrainingLoss](./imgs/train_loss.png)

#### Training performance results

##### Training performance: NVIDIA DGX A100 (8x A100 40GB)
Our results were obtained by running the `resnet50v1.5/training/training_perf.sh` benchmark script in the
[TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow)  NGC container
on NVIDIA DGX A100 (8x A100 40GB) GPUs. Performance numbers (in images per second) were averaged over an entire training epoch.

| GPUs | Batch Size / GPU | Throughput - TF32 + XLA | Throughput - mixed precision + XLA | Throughput speedup (TF32 - mixed precision) | Weak scaling - TF32 + XLA | Weak scaling - mixed precision + XLA |
|----|---------------|---------------|------------------------|-----------------|-----------|-------------------|
| 1  | 256 | 909 img/s  | 2375 img/s    | 2.60x           | 1.00x     | 1.00x             |
| 8  | 256 | 7000 img/s | 17400 img/s   | 2.48x           | 7.70x     | 7.32x             |

##### Training performance: NVIDIA DGX-1 (8x V100 16G)
Our results were obtained by running the `resnet50v1.5/training/training_perf.sh` benchmark script in the
[TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow)  NGC container
on NVIDIA DGX-1 with (8x V100 16G) GPUs. Performance numbers (in images per second) were averaged over an entire training epoch.

| GPUs | Batch Size / GPU | Throughput - FP32 + XLA | Throughput - mixed precision + XLA | Throughput speedup (FP32 - mixed precision) | Weak scaling - FP32 + XLA | Weak scaling - mixed precision + XLA |
|----|---------------|---------------|------------------------|-----------------|-----------|-------------------|
| 1  | 128 (FP32) / 256 (AMP) | 412 img/s  | 1270 img/s | 3.08x           | 1.00x     | 1.00x             |
| 8  | 128 (FP32) / 256 (AMP) | 3170 img/s | 9510 img/s | 3.00x           | 7.69x     | 7.48x             |

##### Training performance: NVIDIA DGX-2 (16x V100 32G)
Our results were obtained by running the `resnet50v1.5/training/training_perf.sh` benchmark script in the
[TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow)  NGC container
on NVIDIA DGX-2 with (16x V100 32G) GPUs. Performance numbers (in images per second) were averaged over an entire training epoch.

| GPUs | Batch Size / GPU | Throughput - FP32 + XLA | Throughput - mixed precision + XLA | Throughput speedup (FP32 - mixed precision) | Weak scaling - FP32 + XLA | Weak scaling - mixed precision + XLA |
|----|---------------|---------------|-------------------------|-------|--------|--------|
| 1  | 128 (FP32) / 256 (AMP) | 432 img/s  | 1300 img/s  | 3.01x | 1.00x  | 1.00x  |
| 16 | 128 (FP32) / 256 (AMP) | 6500 img/s | 17250 img/s | 2.65x | 15.05x | 13.27x |

#### Training Time for 90 Epochs

##### Training time: NVIDIA DGX A100 (8x A100 40GB)

Our results were estimated based on the [training performance results](#training-performance-nvidia-dgx-a100-8x-a100-40g)
on NVIDIA DGX A100 with (8x A100 40G) GPUs.

| GPUs | Time to train - mixed precision + XLA | Time to train - TF32 + XLA |
|---|--------|---------|
| 1 | ~18h   | ~40h   |
| 8 | ~2h    | ~5h   |

##### Training time: NVIDIA DGX-1 (8x V100 16G)

Our results were estimated based on the [training performance results](#training-performance-nvidia-dgx-1-8x-v100-16g)
on NVIDIA DGX-1 with (8x V100 16G) GPUs.

| GPUs | Time to train - mixed precision + XLA | Time to train - FP32 + XLA |
|---|--------|---------|
| 1 | ~25h   |  ~77h   |
| 8 | ~3.5h  |  ~10h |

##### Training time: NVIDIA DGX-2 (16x V100 32G)

Our results were estimated based on the [training performance results](#training-performance-nvidia-dgx-2-16x-v100-32g)
on NVIDIA DGX-2 with (16x V100 32G) GPUs.

| GPUs | Time to train - mixed precision + XLA | Time to train - FP32 + XLA |
|----|-------|--------|
| 1  | ~25h  | ~74h  |
| 16 | ~2h   | ~5h   |

#### Inference performance results

##### Inference performance: NVIDIA DGX A100 (1x A100 40GB)

Our results were obtained by running the `inference_benchmark.sh` inferencing benchmarking script
in the [TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow) NGC container
on NVIDIA DGX A100 with (1x A100 40G) GPU.

**TF32 Inference Latency**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
| 1 | 191.23 img/s | 5.26 ms | 5.29 ms | 5.31 ms | 5.42 ms |
| 2 | 376.83 img/s | 5.34 ms | 5.36 ms | 5.39 ms | 5.56 ms |
| 4 | 601.12 img/s | 6.65 ms | 6.80 ms | 6.93 ms | 7.05 ms |
| 8 | 963.86 img/s | 8.31 ms | 8.63 ms | 8.80 ms | 9.17 ms |
| 16 | 1361.58 img/s | 11.82 ms | 12.04 ms | 12.15 ms | 12.44 ms |
| 32 | 1602.09 img/s | 19.99 ms | 20.48 ms | 20.74 ms | 21.36 ms |
| 64 | 1793.81 img/s | 35.82 ms | 37.22 ms | 37.43 ms | 37.84 ms |
| 128 | 1876.22 img/s | 68.23 ms | 69.60 ms | 70.08 ms | 70.70 ms |
| 256 | 1911.96 img/s | 133.90 ms | 135.16 ms | 135.59 ms | 136.49 ms |

**TF32 Inference Latency + XLA**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
| 1 | 158.67 img/s | 6.34 ms | 6.39 ms | 6.46 ms | 7.16 ms |
| 2 | 321.83 img/s | 6.24 ms | 6.29 ms | 6.34 ms | 6.39 ms |
| 4 | 574.28 img/s | 7.01 ms | 7.03 ms | 7.06 ms | 7.14 ms |
| 8 | 1021.20 img/s | 7.84 ms | 8.00 ms | 8.08 ms | 8.28 ms |
| 16 | 1515.79 img/s | 10.56 ms | 10.88 ms | 10.98 ms | 11.22 ms |
| 32 | 1945.44 img/s | 16.46 ms | 16.78 ms | 16.96 ms | 17.49 ms |
| 64 | 2313.13 img/s | 27.81 ms | 28.68 ms | 29.10 ms | 30.33 ms |
| 128 | 2449.88 img/s | 52.27 ms | 54.00 ms | 54.43 ms | 56.85 ms |
| 256 | 2548.87 img/s | 100.45 ms | 102.34 ms | 103.04 ms | 104.81 ms |

**Mixed Precision Inference Latency**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
| 1 | 223.35 img/s | 4.51 ms | 4.50 ms | 4.52 ms | 4.76 ms |
| 2 | 435.51 img/s | 4.63 ms | 4.62 ms | 4.64 ms | 4.76 ms |
| 4 | 882.00 img/s | 4.63 ms | 4.60 ms | 4.71 ms | 5.36 ms |
| 8 | 1503.24 img/s | 5.40 ms | 5.50 ms | 5.59 ms | 5.78 ms |
| 16 | 1903.58 img/s | 8.47 ms | 8.67 ms | 8.77 ms | 9.14 ms |
| 32 | 1974.01 img/s | 16.23 ms | 16.65 ms | 16.96 ms | 17.98 ms |
| 64 | 3570.46 img/s | 18.14 ms | 18.26 ms | 18.43 ms | 19.35 ms |
| 128 | 3474.94 img/s | 37.86 ms | 44.09 ms | 55.30 ms | 66.90 ms |
| 256 | 3229.32 img/s | 81.02 ms | 96.21 ms | 105.67 ms | 126.31 ms |

**Mixed Precision Inference Latency + XLA**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
| 1 | 174.68 img/s | 5.76 ms | 5.81 ms | 5.95 ms | 6.13 ms |
| 2 | 323.90 img/s | 6.21 ms | 6.26 ms | 6.31 ms | 6.64 ms |
| 4 | 639.75 img/s | 6.25 ms | 6.45 ms | 6.55 ms | 6.79 ms |
| 8 | 1215.50 img/s | 6.59 ms | 6.94 ms | 7.03 ms | 7.25 ms |
| 16 | 2219.96 img/s | 7.29 ms | 7.45 ms | 7.57 ms | 8.09 ms |
| 32 | 2363.70 img/s | 13.70 ms | 13.91 ms | 14.08 ms | 14.64 ms |
| 64 | 3940.95 img/s | 18.76 ms | 26.58 ms | 35.41 ms | 59.06 ms |
| 128 | 3274.01 img/s | 41.70 ms | 52.19 ms | 61.14 ms | 78.68 ms |
| 256 | 3676.14 img/s | 71.67 ms | 82.36 ms | 88.53 ms | 108.18 ms |

##### Inference performance: NVIDIA DGX-1 (1x V100 16G)

Our results were obtained by running the `inference_benchmark.sh` inferencing benchmarking script
in the [TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow) NGC container
on NVIDIA DGX-1 with (1x V100 16G) GPU.

**FP32 Inference Latency**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
|1	|173.35 img/s	|5.79 ms	|5.90 ms	|5.95 ms	|6.04 ms  |
|2	|303.65 img/s	|6.61 ms	|6.80 ms	|6.87 ms	|7.01 ms  |
|4	|562.35 img/s	|7.12 ms	|7.32 ms	|7.42 ms	|7.69 ms  |
|8	|783.24 img/s	|10.22 ms	|10.37 ms	|10.44 ms	|10.60 ms |
|16	|1003.10 img/s	|15.99 ms	|16.07 ms	|16.12 ms	|16.29 ms |
|32	|1140.12 img/s	|28.19 ms	|28.27 ms	|28.38 ms	|28.54 ms |
|64	|1252.06 img/s	|51.12 ms	|51.82 ms	|52.75 ms	|53.45 ms |
|128	|1324.91 img/s	|96.61 ms	|97.02 ms	|97.25 ms	|99.08 ms |
|256	|1348.52 img/s	|189.85 ms	|191.16 ms	|191.77 ms	|192.47 ms|

**Mixed Precision Inference Latency**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
|1	|237.35 img/s	|4.25 ms	|4.39 ms	|4.54 ms	|5.30 ms  |
|2	|464.94 img/s	|4.32 ms	|4.63 ms	|4.83 ms	|5.52 ms  |
|4	|942.44 img/s	|4.26 ms	|4.55 ms	|4.74 ms	|5.45 ms  |
|8	|1454.93 img/s	|5.57 ms	|5.73 ms	|5.91 ms	|6.51 ms  |
|16	|2003.75 img/s	|8.13 ms	|8.19 ms	|8.29 ms	|8.50 ms  |
|32	|2356.17 img/s	|13.69 ms	|13.82 ms	|13.92 ms	|14.26 ms |
|64	|2706.11 img/s	|23.86 ms	|23.82 ms	|23.89 ms	|24.10 ms |
|128	|2770.61 img/s	|47.04 ms	|49.36 ms	|62.43 ms	|90.05 ms |
|256	|2742.14 img/s	|94.67 ms	|108.02 ms	|119.34 ms	|145.55 ms|

**Mixed Precision Inference Latency + XLA**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
|1	|162.95 img/s	|6.16 ms	|6.28 ms	|6.34 ms	|6.50 ms  |
|2	|335.63 img/s	|5.96 ms	|6.10 ms	|6.14 ms	|6.25 ms  |
|4	|637.72 img/s	|6.30 ms	|6.53 ms	|7.17 ms	|8.10 ms  |
|8	|1153.92 img/s	|7.03 ms	|7.97 ms	|8.22 ms	|9.00 ms  |
|16	|1906.52 img/s	|8.64 ms	|9.51 ms	|9.88 ms	|10.47 ms |
|32	|2492.78 img/s	|12.84 ms	|13.06 ms	|13.13 ms	|13.24 ms |
|64	|2910.05 img/s	|22.66 ms	|21.82 ms	|24.71 ms	|48.61 ms |
|128	|2964.31 img/s	|45.25 ms	|59.30 ms	|71.42 ms	|98.72 ms |
|256	|2898.12 img/s	|90.53 ms	|106.12 ms	|118.12 ms	|150.78 ms|

##### Inference performance: NVIDIA DGX-2 (1x V100 32G)

Our results were obtained by running the `inference_benchmark.sh` inferencing benchmarking script
in the [TensorFlow 20.06-tf1-py3 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow) NGC container
on NVIDIA DGX-2 with (1x V100 32G) GPU.

**FP32 Inference Latency**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
|1	|136.44 img/s	|7.34 ms	|7.43 ms	|7.47 ms	|7.54 ms    |
|2	|215.38 img/s	|9.29 ms	|9.42 ms	|9.46 ms	|9.59 ms    |
|4	|289.29 img/s	|13.83 ms	|14.08 ms	|14.16 ms	|14.40 ms   |
|8	|341.77 img/s	|23.41 ms	|23.79 ms	|23.86 ms	|24.11 ms   |
|16	|394.36 img/s	|40.58 ms	|40.87 ms	|40.98 ms	|41.41 ms   |
|32	|414.66 img/s	|77.18 ms	|78.05 ms	|78.29 ms	|78.67 ms   |
|64	|424.42 img/s	|150.82 ms	|152.99 ms	|153.44 ms	|154.34 ms  |
|128	|429.83 img/s	|297.82 ms	|301.09 ms	|301.60 ms	|302.51 ms  |
|256	|425.72 img/s	|601.37 ms	|605.74 ms	|606.47 ms	|608.74 ms  |

**Mixed Precision Inference Latency**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
|1	|211.04 img/s	|4.77 ms	|5.05 ms	|5.08 ms	|5.15 ms    |
|2	|381.23 img/s	|5.27 ms	|5.40 ms	|5.45 ms	|5.52 ms    |
|4	|593.13 img/s	|6.75 ms	|6.89 ms	|6.956 ms	|7.02 ms   |
|8	|791.12 img/s	|10.16 ms	|10.35 ms	|10.43 ms	|10.68 ms   |
|16	|914.26 img/s	|17.55 ms	|17.80 ms	|17,89 ms	|18.19 ms   |
|32	|972.36 img/s	|32.92 ms	|33.33 ms	|33.46 ms	|33.61 ms   |
|64	|991.39 img/s	|64.56 ms	|65.62 ms	|65.92 ms	|66.35 ms  |
|128	|995.81 img/s	|128.55 ms	|130.03 ms	|130.37 ms	|131.08 ms  |
|256	|993.39 img/s	|257.71 ms	|259.26 ms	|259.62 ms	|260.36 ms  |

**Mixed Precision Inference Latency + XLA**

|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**|
|--------------|------------------|---------------|---------------|---------------|---------------|
|1      |167.01 img/s	|6.01 ms	|6.12 ms	|6.14 ms	|6.18 ms  |
|2	|333.67 img/s	|6.03 ms	|6.11 ms	|6.15 ms	|6.23 ms  |
|4	|605.94 img/s	|6.63 ms	|6.79 ms	|6.86 ms	|7.02 ms  |
|8	|802.13 img/s	|9.98 ms	|10.14 ms	|10.22 ms	|10.36 ms |
|16	|986.85 img/s	|16.27 ms	|16.36 ms	|16.42 ms	|16.52 ms |
|32	|1090.38 img/s	|29.35 ms	|29.68 ms	|29.79 ms	|30.07 ms |
|64	|1131.56 img/s	|56.63 ms	|57.22 ms	|57.41 ms	|57.76 ms |
|128	|1167.62 img/s	|109.77 ms	|111.06 ms	|111.27 ms	|111.85 ms|
|256	|1193.74 img/s	|214.46 ms	|216.28 ms	|216.86 ms	|217.80 ms|

## Release notes

### Changelog
1. March, 2019
  * Initial release
2. May, 2019
  * Added DALI support
  * Added scripts for DGX-2
  * Added benchmark results for DGX-2 and XLA-enabled DGX-1 and DGX-2.
3. July, 2019
  * Added Cosine learning rate schedule
4. August, 2019
  * Added mixup regularization
  * Added T4 benchmarks
  * Improved inference capabilities
  * Added SavedModel export
5. January, 2020
  * Removed manual checks for dataset paths to facilitate cloud storage solutions
  * Move to a new logging solution
  * Bump base docker image version
6. March, 2020
  * Code cleanup and refactor
  * Improved training process
7. June, 2020
  * Added benchmark results for DGX-A100
  * Updated benchmark results for DGX-1, DGX-2 and T4
  * Updated base docker image version
8. August 2020
  * Updated command line argument names
  * Added support for syntetic dataset with different image size
9. January, 2022
  * Added barrier at the end of multiprocess run
10. April, 2023
  * Ceased maintenance of ConvNets in TensorFlow1

### Known issues
Performance without XLA enabled is low due to BN + ReLU fusion bug.

repository: NVIDIA/DeepLearningExamples

gha_language: Jupyter Notebook

repo_name: NVIDIA/DeepLearningExamples


text:
[![Build Status](https://travis-ci.org/squeedee/pymn.png?branch=master)](https://travis-ci.org/squeedee/pymn)

Patterns You May Need
=======

Other patterns, not just the one your framework provides, are quite useful. Especially as your app gets bigger.

Here are some (one so far) patterns that you may need.

## Installation

Add this line to your application's Gemfile:

    gem 'pymn'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install pymn

## Usage

### Chain Of Responsibility

TODO: example usage

For now, take a look at:

https://github.com/squeedee/pymn/blob/master/integrations/fixtures/chain_of_responsibility.rb
https://github.com/squeedee/pymn/blob/master/integrations/fixtures/chain_of_responsibility_factory.rb

license: MIT

repository: squeedee/pymn

branch_name: refs/heads/master

extension: md

license_type: permissive

repo_name: squeedee/pymn


text:
# ggsoccer 0.1.8 (In progress)

- Add IMPECT pitch dimensions (`pitch_impect`)

# ggsoccer 0.1.7

-   Add support for custom goals markings
-   Add `pitch_statsperform` alias for Opta data

# ggsoccer 0.1.6

-   Add support for Tracab pitch dimensions (`pitch_tracab` and `make_pitch_tracab`)
-   Make direction arrow an annotation
    -   This ensures it will display properly for a ggplot without any data

# ggsoccer 0.1.5

-   Make line widths consistent across all pitch elements
-   Convert coordinates between different pitch specifications
-   Add UEFA-standard pitch dimensions (`pitch_international`)

# ggsoccer 0.1.4

-   Released to CRAN!
-   Link penalty box arc to pitch specification
    -   Fixes a previous issue in which the edge of a circle could be seen poking out from behind the pitch (#8).

# ggsoccer 0.1.3

-   Generate pitch markings from a generic specification
    -   This makes ggsoccer compatible with any data provider

# ggsoccer 0.1.2

-   Show pitch with `scale_*_reverse`
    -   Centre-circle and penalty box arcs still do not properly render when `scale_*_reverse` is used
    -   It appears this is an issue with ggplot2 ([#3120](https://github.com/tidyverse/ggplot2/issues/3120))

# ggsoccer 0.1.1

-   Display the whole pitch by default

# ggsoccer 0.1.0

-   Basic pitch map functions
-   Added a `NEWS.md` file to track changes to the package.

repository: Torvaney/ggsoccer

gha_language: R

gha_license_id: NOASSERTION

repo_name: Torvaney/ggsoccer


text:
# Numbers, Letters and Variables

* What does puts do?
  puts prints the results to the console on a new line but returns nil.

* What is an integer? What is a float?
  An integer is a whole number with no decimals or decimal points. A float is a number with decimal points.

* What is the difference between float and integer division? How would you explain the difference to someone who doesn't know anything about programming?
  Integer division always rounds down to the next whole number. Float division doesn't round and gives the answer with decimals. I'd explain this to someone who doesn't know anything about programming by using the example of buying concert tickets. The answer that matters would be the lowest whole number, since you wouldn't be able to buy part of a ticket.

* Hours in a year
``` puts 24 * 365 ```

* Minutes in a decade
``` puts 24 * 60 * 365 * 10 ```

* Exercise Links
[Defining Variables](defining-variables.rb)
[Simple String Methods](simple-string.rb)
[Local Variables and Basic Arithmetic](basic-math.rb)

* How does Ruby handle addition, subtraction, multiplication, and division of numbers?
  Addition uses the + sign, subtraction uses the - sign, multiplication uses *, and division uses the / sign.

* What is the difference between integers and floats?
  Integers are whole numbers with no decimal points, and floats are numbers with the decimal points.

* What is the difference between integer and float division?
   Integer division always rounds down to the next whole number. Float division doesn't round and gives the answer with decimals.

* What are strings? Why and when would you use them?
  Strings are groups of letters or characters. You'd use them to print words and text to the screen.

* What are local variables? Why and when would you use them?
  A local variable is a variable given local scope. You'd use them as variables that needed to be reused in your current scope. So if it's in a certain file or function, you'd want to use a local variable.

* How was this challenge? Did you get a good review of some of the basics?
  I thought it was good. I would have preferred to do more active exercises, but felt the reading was a good start.

gha_language: Ruby


text:
# Setup Guide

## Dependency

Conference signaling server from [Samvad](https://github.com/namdu1radio/samvad) project.

## Setting up client

1. Move to a temporary directory by issuing `cd /tmp` in terminal.
2. Clone this repository by issuing `git clone https://github.com/namdu1radio/prasna.git` command in terminal, internet connection is necessary for this step.
3. Nginx setup,
  * If Nginx (or Apache) is not installed already, install it using `sudo apt-get install nginx`
  * Now create a `quiz` directory in Nginx's `www` folder by issuing `sudo mkdir /var/www/html/quiz` command in terminal
  * Now enable write permission to this directory by issuing `sudo chown <YOURUSERNAME>:www-data /var/www/html/quiz` command in terminal
4. Copy the contents of `/tmp/prasna/client` to `quiz` directory by issuing `cp -r /tmp/prasna/client/* /var/www/html/quiz/` command in terminal.
5. Open `/var/www/html/quiz/js/quiz.js` in your favorite text editor and change line number `51` and replace the IP `<IP_ADDRESS>` with IP address of your current machine, this can be found by issuing `ifconfig` command in the terminal. Leave everything else including `http` protocol and `1337` port unchanged. Once you have made the changes, make sure the file is saved.
6. Open `/var/www/html/quiz/js/audio-stream.js` in your favorite text editor and change line number `20` and replace the IP `<IP_ADDRESS>` with IP address of your current machine, this can be found by issuing `ifconfig` command in the terminal. Leave everything else including `http` protocol and `443` port unchanged. Once you have made the changes, make sure the file is saved.

## Setting up admin dashboard

1. Move to the clone repository directory from earlier steps, by issuing `cd /tmp/prasna` in terminal.
2. Copy the contents of `/tmp/prasna/admin` to `quiz` directory by issuing `cp -r /tmp/prasna/admin/ /var/www/html/quiz/` command in terminal.
3. Open `/var/www/html/quiz/admin/js/admin.js` in your favorite text editor and change line number `45` and replace the IP `<IP_ADDRESS>` with IP address of your current machine, this can be found by issuing `ifconfig` command in the terminal. Leave everything else including `http` protocol and `1337` port unchanged. Once you have made the changes, make sure the file is saved.
4. Open `/var/www/html/quiz/admin/js/audio-broadcast.js` in your favorite text editor and change line number `22` and replace the IP `<IP_ADDRESS>` with IP address of your current machine, this can be found by issuing `ifconfig` command in the terminal. Leave everything else including `http` protocol and `443` port unchanged. Once you have made the changes, make sure the file is saved.

## Setting up server

1. Install NodeJS in your Raspberry Pi, if it's not already installed, issue following commands in the given sequence
  * `sudo apt-get update`
  * `curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -`
  * `sudo apt-get install -y nodejs`
2. Copy the `/tmp/prasna/server` directory to your home directory by issuing `cp -r /tmp/prasna/server ~/quizServer`
3. Change directory in terminal to this directory, by issuing `cd ~/quizServer` in terminal.
4. Install the dependency of the server by issuing `npm install` command, internet connection is necessary for this step. The server is ready after this step.

# Launching

## Starting the server
1. Change directory to `quizServer` directory by issuing `cd ~/quizServer` in terminal.
2. Start the server by issuing `sudo node app.js` command in terminal.
3. Minimize the terminal so that the server keeps running in background inside the terminal.

## Accessing the quiz webpage

1. First launch the Quiz admin dashboard by visiting `http://xxx.xxx.xxx.xxx/quiz/admin` and entering default password `123`. After that allow mic permission.
2. In client devices open Quiz client webpage by visiting `http://xxx.xxx.xxx.xxx/quiz` in any modern web-browser. Client can join the Quiz by entering their name and age and clicking Join button.

Replae `xxx.xxx.xxx.xxx` with the IP of the machine where Nginx and quiz are setup. The accessing device, and the Nginx, the Conference server and the Quiz server - should be all part of same network.

repository: carlhuth/prasna

repo_name: carlhuth/prasna


text:
# Node JSON Config Server
Simple JSON config service that allows simple configs to be accessed via REST

## Using the API server
Implmented as a simple http://host:port/config/:id idea where the namne of the config file is stored as config.id.json and tehn served based on that.

### Getting started

npm install
```
And that's really about it (see, I said it was simple!). To fire up the server and have it do stuff, you'll need to start it with the familiar command:

```
npm start
```

### Accessing the server and returning data

The server should be running by now, and you can visit `http://localhost:3001/config` to see it in action.

## Expanding the server

1. Add a new config JSON file with your relevant data to the main data entry point for the project, `./data`
2. Add a route file that will access this data into `./routes/[your route file].js` -- hint: use the `./routes/users.js` as a starting point
3. Add your new route file into the main routes file located at `./routes/routes.js`

branch_name: refs/heads/main


text:
# Depricated

Please use https://github.com/mqttjs/mqtt-elements

# mqtt-connection

## install

`bower install sandro-k/mqtt-connection`

## bundle MQTT.js and chrome.net

`npm install chrome-net mqtt`

`browserify -r chrome-net -r mqtt -o build/bundel.js`

repository: sandro-k/mqtt-connection

repo_name: sandro-k/mqtt-connection


text:
---
title: Rule SoFStartZoneID
searchTitle: Lua Rule SoFStartZoneID
weight: 1
hidden: true
menuTitle: Rule SoFStartZoneID
---
## SoFStartZoneID

This represents a SoFStartZoneID Rule
```lua
Rule.SoFStartZoneID
```

repository: xackery/eqquestapi

repo_name: xackery/eqquestapi


text:
# Terraform::AzureRM::DataLakeAnalyticsAccount

Manage an Azure Data Lake Analytics Account.

## Properties

`Name` - (Required) Specifies the name of the Data Lake Analytics Account. Changing this forces a new resource to be created. Has to be between 3 to 24 characters.

`ResourceGroupName` - (Required) The name of the resource group in which to create the Data Lake Analytics Account.

`Location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created.

`DefaultStoreAccountName` - (Required) Specifies the data lake store to use by default. Changing this forces a new resource to be created.

`Tier` - (Optional) The monthly commitment tier for Data Lake Analytics Account. Accepted values are `Consumption`, `Commitment_100000AUHours`, `Commitment_10000AUHours`, `Commitment_1000AUHours`, `Commitment_100AUHours`, `Commitment_500000AUHours`, `Commitment_50000AUHours`, `Commitment_5000AUHours`, or `Commitment_500AUHours`.

`Tags` - (Optional) A mapping of tags to assign to the resource.

## Return Values

### Fn::GetAtt

`Id` - The Date Lake Store ID.

## See Also

* [azurerm_data_lake_analytics_account](https://www.terraform.io/docs/providers/azurerm/r/data_lake_analytics_account.html) in the _Terraform Provider Documentation_


text:
---
layout: page
title: Great Quotes from "Working Effectively with Legacy Code" by Michael Feathers
categories: []
tags: [Michael Feathers]
date: 2018-03-14 01:00:00 PM UTC
permalink: /memorabilia/books/quotes-from-working-effectively-with-legacy-code/
---

Some uplifting criticisms and some encouraging words from ["Working Effectively with Legacy Code" of Michael Feathers](https://www.bookdepository.com/Working-Effectively-with-Legacy-Code-Michael-Feathers/9780131177055?a_aid=jflaga)

(The quotes below are words that might help change the mindset of programmers on dealing with legacy code. They are not about how to _reverse_ the rot in a legacy code, which is what the majority of the book contains. Read the book if you want to know about the techniques. :smile:)

### Preface

> "**Code without tests is bad code.**

> It doesn't matter how well written it is; it doesn't matter how pretty or object-oriented or well-encapsulated it is.

> **With tests, we can change the behavior of our code quickly and verifiably.**

> Without them, we really don't know if our code is getting better or worse."

> --- Michael Feathers

----------

### Chapter 6

> When I work with teams, I often start by asking them to take part in an **experiment**. For an iteration, we try to make no change to the code without having tests that cover the change. If anyone thinks that they can't write a test, they have to call a quick meeting in which they ask the group whether it is possible to write the test.

The beginnings of those iterations are terrible. People feel that they aren't getting all the work done that they need to. But slowly, they start to discover that they are revisiting better code. Their changes are getting easier, and they know in their gut that this is what it takes to move forward in a better way.

It takes time for a team to get over that hump, **but if there is one thing that I could instantaneously do for every team in the world, it would be to give them that shared experience, that experience that you can see in their faces: "Boy, we aren't going back to that again."**

> The biggest obstacle to improvement in large code bases is the existing code. "Duh." you might say. But I'm not talking about how hard it is to work in difficult code; **I'm talking about what that code leads you to believe.**

If you spend most of your day wading through ugly code, it's very easy to believe that it will alway be ugly and that any little thing that you do to make it better is simply not worth it. You might think, "What does it matter whether I make this little peice nicer if 90 percent of the time I'll still be working with murky slime? Sure, I can make this piece better, but what will that do for me this afternoon? Tomorrow?"

Well, if you look at it that way, I'd have to agree with you. No much.

**But if you consistently do these little improvements, your system will start to look significantly different over the course of a couple of months.** At some point, you'll come to work in the morning expecting to sink your hands into some slime and discover, "Huh, this code looks pretty good. It looks like someone was in here refactoring recently." At that point, when you feel the difference between good code and bad code in your gut, you are a changed person...

### Chapter 7

> **The human mind has some interesting qualities. If we have to perform a short task (5-10 seconds long) and we can only take a step once every minute, we usually do it and then pause.** If we have to do some work to figure out what to do at the next step, **we start to plan**. After we plan, our minds wander until we can do the next step.

**If we compress the time between steps down from a minute to a few seconds, the quality of the mental work becomes different.** We can use feedback to try out approaches quickly. Our work becomes more like driving than like waiting at a bus stop. Our concentration is more intense because we aren't constantly waiting for the next chance to do something. Most important, the amount of time that it takes us to notice and correct mistakes is much smaller

### Chapter 8

> ... if we have tests in place, we are able to remove duplication easily.

### Chapter 13

> No, finding bugs in legacy code usually isn't a problem. In terms of strategy, it can actually be misdirected effort. **It is usually better to do something that helps your team start to write correct code consistently.** The way to win is to concentrate effort on not putting bugs into code in the first place.

Automated tests are a very important tool, but not for bug finding --- not directly, at least. In general, automated tests should specify a goal that we'd like to fulfill or attempt to preserve behavior that is already there. In the natural flow of development, **tests that specify become tests that preserve**. You will find bugs, but usually not the first time that a test is run. You find bugs in later runs when you change behavior that you didn't expect to.

### Chapter 17

> **The brutal truth is that architecture is too important to be left exclusively to a few people.** It's fine to have an architect, but the key way to keep an architecture intact is to make sure that everyone on the team knows what it is and has a stake in it.

**Every person who is touching the code should know the architecture, and everyone else who touches the code should be able to benefit from what that person has learned.** When everyone is working off of the same set of ideas, the overall system intelligence of the team is amplified. If you have, say, a team of 20 and only 3 people know the architecture in detail, either those 3 have to do a lot to keep the other 17 people on track, or the other 17 people just make mistakes caused by unfamiliarity with the big picture.

### Chapter 21

> **One of the startling things that you discover when you start removing duplication zealously is that designs emerge.** You don't have to plan most of the knobs in you application; they just happen.

> Duplication removal is a powerful way of distilling a design. It not only makes a design more flexible, but it also makes change faster and easier.

> When we remove duplication, our code often naturally starts to fall in line with the Open/Closed Principle.

### Chapter 23

> ... The truth is, there are many different kind of "smart." Holding on to a lot of state mentally can be useful, but it doesn't really make us better at desicion making. At this point in my career, I think I'm a much better programmer than I used to be, even though I know less about the details of each language I work in. Judgement is a key programming skill, and we can get into trouble when we try to act like super-smart programmers.

### Chapter 24

> Working in legacy code is difficult. There is no denying it. Although every situation is different, one thing is going to make the job worth it to you as a programmer or not: figuring out what is in it for you.

> The key to thriving in legacy code is finding what motivates you.

> If morale is low on your team, and it's low because of code quality, here's something that you can try: Pick the ugliest most obnoxious set of classes in the project, and get them under test. **When you've tackles the worst problem as a team, you'll feel in control of the situation. I've seen it again and again.**


text:
# Progressive Delivery

## Deploy ServiceMesh

```shell
oc apply -f ./servicemesh/operators.yaml
oc new-project istio-system
oc apply -f ./servicemesh/control-plane.yaml -n istio-system
```

### Deploy test application
```shell
oc new-project bookinfo
oc label namespace bookinfo istio-injection=enabled
oc apply -n bookinfo -f https://raw.githubusercontent.com/Maistra/istio/maistra-2.4/samples/bookinfo/platform/kube/bookinfo.yaml
oc apply -n bookinfo -f https://raw.githubusercontent.com/Maistra/istio/maistra-2.4/samples/bookinfo/networking/bookinfo-gateway.yaml
export istio_gateway_url=$(oc get route istio-ingressgateway -n istio-system -o jsonpath='{.spec.host}')
curl http://${istio_gateway_url}/productpage
```

## Deploy OpenShift Gitops

```sh
oc apply -f ./gitops/operator.yaml
oc apply -f ./gitops/argocd.yaml
```

## Preparing for Progressive delivery

we are now going to delete the reviews deployments, which feature different versions (v1, v2, v3) and refactor this implementation with roolouts. At the time of the writing, the three images were respectively:
- quay.io/maistra/examples-bookinfo-reviews-v1:2.4.0
- quay.io/maistra/examples-bookinfo-reviews-v2:2.4.0
- quay.io/maistra/examples-bookinfo-reviews-v3:2.4.0

In the spirit of the original book info demo, we will proceed with two canary rollouts, going from v1 to v3.
The following commands prepare the environment.

```sh
oc delete deployment reviews-v1 -n bookinfo
oc delete deployment reviews-v2 -n bookinfo
oc delete deployment reviews-v3 -n bookinfo
oc apply -f ./rollouts/rollout-controller.yaml -n bookinfo
oc apply -f ./rollouts/deployment.yaml -n bookinfo
oc apply -f ./rollouts/virtual-service.yaml -n bookinfo
oc apply -f ./rollouts/destination-rule.yaml -n bookinfo
oc apply -f ./rollouts/analysis-template.yaml -n bookinfo
oc apply -f ./rollouts/rollout.yaml -n bookinfo

```

first rollout:

```sh
oc argo rollouts set image reviews reviews=quay.io/maistra/examples-bookinfo-reviews-v2:2.4.0
oc argo rollouts get rollout reviews --watch -n bookinfo
```

second rollout

```sh
oc argo rollouts set image reviews reviews=quay.io/maistra/examples-bookinfo-reviews-v3:2.4.0
oc argo rollouts get rollout reviews --watch -n bookinfo
```

gha_language: Shell


text:
---
layout: default
---

# 1996-10-04 - RSA's Official Permission

## Header Data

From: The Deviant<EMAIL_ADDRESS>To<EMAIL_ADDRESS>Message Hash: 9bb540621b2849d0c4ac0f3e1a5a9a33342c54341030c388fe2507e08307a898

Message ID<EMAIL_ADDRESS>Reply To: _N/A_

UTC Datetime: 1996-10-04 17:25:50 UTC

Raw Date: Sat, 5 Oct 1996 01:25:50 +0800

## Raw message

```
{% raw  %}From: The Deviant<EMAIL_ADDRESS>Date: Sat, 5 Oct 1996 01:25:50 +0800
To<EMAIL_ADDRESS>Subject: RSA's Official Permission
Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

---------- Forwarded message ----------

   RSA Optimistic on User Benefits of Administration's Recent Key
   Recovery Initiative Announcement Further policy change required for US
   vendors to be competitive worldwide

   REDWOOD CITY, Calif.---Oct. 2nd, 1996--RSA Data Security, Inc., a
   wholly-owned subsidiary of Security Dynamics Technologies, Inc.
   (NASDAQ: SDTI), issued the following comments on the administration's
   recent announcement of a Key Recovery Initiative:

   The administration's proposed Key Recovery Initiative is a positive
   step towards meeting the needs of individuals and organizations that
   buy and use products which utilize encryption. However, the proposal
   leaves significant competitive issues unresolved for suppliers who
   compete overseas.

   Modern encryption and authentication technologies are crucial to the
   growth of electronic commerce and the health of the future global
   electronic economy. The continued leadership of American computer and
   software firms in the world market depends on their ability to provide
   competitive solutions for consumers and business around the world.
   These consumers and businesses depend increasingly on encryption and
   authentication technologies -- such as those developed at RSA -- to
   provide solutions that protect the privacy of consumer purchases,
   personal medical information, sensitive corporate data, and electronic
   commerce and funds transfers as they travel over the global Internet.

   US government agencies, however, have long insisted that they must
   have potential access to all encrypted information for law enforcement
   purposes, and have advanced several proposals towards those ends.

   To date, these proposals have met with little support from the user
   and vendor communities due to concerns about privacy and
   competitiveness. This new proposal from the administration, however,
   is a move in the right direction for users.

   One positive step is that the administration has indicated, for the
   first time in over six years of discussion, that it will lift all key
   size restrictions on the export of products which utilize
   cryptography, provided that manufacturers provide a viable means of
   key recovery for legitimate government access.

   In addition, under the administrations proposal, industry, not
   government, will develop and propose the actual key recovery
   mechanisms. This will to result in more effective solutions to
   managing and recovering keys.

   Finally, the proposal addresses the concerns of users that any third
   party designated to hold user keys might improperly disclose those
   keys, thereby compromising a user's right to privacy. The
   administration has agreed that under certain circumstances,
   organizations would be allowed to "self-escrow" their own encryption
   keys.

   RSA is confident that industry can develop and gain approval for
   several excellent key recovery mechanisms that would be acceptable to
   government concerns. In fact, RSA has been a pioneer in this field
   with our RSA Emergency Access(tm) technology in its award-winning RSA
   SecurPC(tm) product. In the case of SecurPC, companies using the product
   can use Emergency Access keys with RSA's unique secret-splitting
   technology to gain access to critical information in the event of an
   emergency.

   The recently announced Key Recovery Alliance, of which RSA is a part,
   is chartered to provide a flexible, workable solution for users
   working within the government's proposed key recovery framework.
   Members of the group are working on technology which will allow users
   to maintain the privacy of their keys while allowing legitimate
   business or law enforcement authorities to recover keys when
   appropriate. It will also address challenges that arise when a user
   must comply with the differing encryption policies in countries around
   the world. The technology could allow products to provide the
   flexibility a user needs to take full advantage of the maximum privacy
   allowed in their locality, while maintaining interoperability and
   information exchange with other users regardless of location.

   It is not clear, however, to what extent the administration's proposal
   provides relief to US software and hardware companies who must compete
   with foreign suppliers. These foreign suppliers, not subject to US
   law, can provide strong, non-key-recovery encryption in their
   products.

   Today, most major computer and software solutions firms derive
   significant revenues from outside the United States. The government's
   proposal, while satisfying the US government's needs, does little to
   enhance the competitiveness of American products overseas. Robust
   encryption products are already available from many overseas
   suppliers, and U.S. market share in encryption-enabled products is
   under siege. Under this proposal, it appears that U.S. companies will
   still be prohibited from selling non-key-recovery encryption solutions
   in overseas markets, creating a significant barrier to their
   competitiveness.

   RSA looks forward to additional announcements by the administration
   that specifically address this issue and provide competitive relief
   for the US computer software and hardware industries.

   RSA Data Security, Inc.

   RSA Data Security, Inc., a wholly-owned subsidiary of Security
   Dynamics Technologies, Inc. (NASDAQ: SDTI), is the world's brand name
   for cryptography, with more than 75 million copies of RSA encryption
   and authentication technologies installed and in use worldwide. RSA
   technologies are part of existing and proposed standards for the
   Internet and World Wide Web, ITU, ISO, ANSI, IEEE, and business,
   financial and electronic commerce networks around the globe. The
   company develops and markets platform-independent developer's kits and
   end-user products and provides comprehensive cryptographic consulting
   services.

   Founded in 1982 by the inventors of the RSA Public Key Cryptosystem,
   the company is headquartered in Redwood City, Calif.

   -0-

   Note to Editors: BSAFE and TIPEM are trademarks of RSA Data Security,
   Inc. All other product and brand names are trademarks or registered
   trademarks of their respective companies.

   | [1]Al Gore's Statement | [2]Jim's Testimony | [3]IBM's Alliance |

   CONTACT:

   Corman/Croel

   Marketing & Communications (for RSA)

   Patrick Corman, 415/326-9648

<EMAIL_ADDRESS>

---------- End Forwarded message ----------

This is definatly bad...

If you want to look it up yourselves, its at

http://www.rsa.com/PRESSBOX/releases/keyrecov.htm

 --Deviant
They seem to have learned the habit of cowering before authority even when
not actually threatened.  How very nice for authority.  I decided not to
learn this particular lesson.
                -- Richard Stallman

{% endraw %}
```

## Thread

+ Return to [October 1996](/archive/1996/10)

+ Return to "[The Deviant <deviant@pooh-corner.com>](/authors/the_deviant_deviant_at_poohcorner_com_)"

+ 1996-10-04 (Sat, 5 Oct 1996 01:25:50 +0800) - RSA's Official Permission - _The Deviant<EMAIL_ADDRESS>

gha_license_id: MIT


text:
---
coverImageUri: ''
title: "Gulp, Grunt, Webpack: What's a Dev to Choose? [Screencast]"
datetime: '2017-10-20T12:26:51.000Z'
categories: 'technology'
tags: '#THATconference,alm,devops,grunt,gulp,javascript,webpack'
---

This past summer I had the pleasure of presenting at
[THAT Conference 2017](https://www.thatconference.com/sessions/session/11122 "THAT Conference | Gulp, Grunt, Webpack: What's a Dev to Choose? by Brandon Martinez") with
my talk titled
[Gulp, Grunt, Webpack: What's a Dev to Choose?](https://www.thatconference.com/sessions/session/11122 "THAT Conference | Gulp, Grunt, Webpack: What's a Dev to Choose? by Brandon Martinez").
In my session, I demonstrated two of the most popular JavaScript task runners,
[Grunt](https://gruntjs.com/) and [Gulp](https://gulpjs.com/), being used with
two of the most popular bundling systems, [webpack](https://webpack.js.org/) and
[browserify](http://browserify.org/), and how they can fit into your JavaScript
workflow.

If you were able to catch my presentation, thank you for coming out to support
me! If you didn't have the opportunity, or you want a refresher on the content,
then you're in for a treat: I recorded a streamlined version of my talk as a
screencast that can be seen over at
[the Skyline Technologies blog; check it out!](https://www.skylinetechnologies.com/Blog/Skyline-Blog/October_2017/gulp-grunt-webpack-what-is-a-dev-to-choose)

All of the slides and source can be found on my
[GitHub Repository](https://github.com/brandonmartinez/mm-gulp-grunt-webpack-comparison).
The
[slides can also be viewed on GitHub Pages](https://brandonmartinez.github.io/mm-gulp-grunt-webpack-comparison/slides/#/).

repository: brandonmartinez/brandonmartinez

repo_name: brandonmartinez/brandonmartinez


text:
# selenideConsole
A console for trying out selenide commands

## Getting started ###
- Download the latest release jar from this SelenideCode project.
- Download the chromedriver.exe and place them bot in the same folder.
- Start the jar file with double click
- Have fun

### Possible command which could be entered are:

    open("http://www.google.com")
Open the given url

    $(" a css selector ")
Select a element for one of the following functions

#### Actions on an element (appended with dot)

    .click()
Performs a click on the selected element

    .shouldHave(" your text to test")
Check if the text matches the inner text of the element (Result shown in log)

    .text()
Will print out the text of the selected element in the console

    .mark()
Marks the selected element in purple

    .setValue(" your text value ")
Enters the given text value into the selected element (should be a textarea or input field)


text:
# Ticket Granting Ticket
**Golden / Silver Ticket**

Scripts to help hunt for possible golden/silver TGT tickets, by comparing the domain policy of the Max-Ticket-Age to cached tickets on a local system.

You will need the GroupPolicy and Active Directory [cmdlet](https://technet.microsoft.com/en-us/library/dd378937(WS.10).aspx)

If you use the modules, ensure you put them in the modules directory in order to be used.

repository: rahmiy/TGT---Golden-Silver-Ticket

repo_name: rahmiy/TGT---Golden-Silver-Ticket


text:
## Docker container solution for Spryker deploy
There is Dockerfile for build Yves and Zed docker containers and additional services container configurations for run Spyrker shop suite.
## Quick installation
### Create a new SSH key pair:
Linux/MacOS:

```
ssh-keygen -b 2048 -m PEM -t rsa -f jenkins/id_rsa -q -N ""
```

Windows:

```
Git Bash:
1. Download and install Git for Windows: https://git-scm.com/download/win
  a. Select to Use Git from the Windows Command Prompt.
  b. Select to Use OpenSSL library.
  c. Accept the default extra option configuration by clicking Install.
2. Launching GitBash
  a. Chenge directory to the docker-shop-suite
  b. ssh-keygen.exe  -b 2048 -m PEM -t rsa -f jenkins/id_rsa -q -N ""
```

### Run buid and start docker-compose

```
docker-compose build
docker-compose up -d
```

You can start Jenkins jobs only when http://www.de.demoshop.local came UP.
(in the other case, you will face with "Connection refused" error):
```
[SSH] Exception:java.net.ConnectException: Connection refused (Connection refused)
com.jcraft.jsch.JSchException: java.net.ConnectException: Connection refused (Connection refused)
```

### NewRelic usage
If you plan to use the [NewRelic](https://newrelic.com/) for monitoring please define the `NEWRELIC_KEY` as the environment variable of the application container.

### Spryker cronjobs
The [Spryker cronjobs sheduling](https://academy.spryker.com/developing_with_spryker/resources_and_developer_tools/cronjob_scheduling.html) should be correctly setup for shop suite publish and sync working.
The jenkins container setup for this needs, but now the console command:
```
vendor/bin/console setup:jenkins:generate
```
works correctly if Jenkins is installed on the same server as Zed. But in our case we have Jenkins in the separate Docker container, out of Zed. So you need to add [jobs](https://github.com/spryker-shop/suite/blob/master/config/Zed/cronjobs/jobs.php) to your Jenkins container:
```
http://os.de.demoshop.local:9090/
```
and this jobs should run remotely on Zed server, for example with the [Jenkins SSH plugin](https://wiki.jenkins.io/display/JENKINS/SSH+plugin).

## Documentation
[Spryker Documentation](https://academy.spryker.com)

repository: spryker/docker-shop-suite

gha_language: HTML

repo_name: spryker/docker-shop-suite


text:
# LOOTWELL

Lootwell is an addon for World of Warcraft: Classic, designed to make the process of loot council faster/more efficient, and to be a good record keeper as to how loot has been distributed.
It includes raid roster features, displaying the raider, their rank, role, loot acquired, and so on.

Planned Features:

0.1.0:
Main Menu, containing:
- Guild Roster (Name, Rank, Role)
    - Ability to add/edit/remove members from guild to roster
- Gear list for each member
    - Can view item tooltip
    - Lists name, when won (just as a note for now), who drops, any set reference
- Ability to add items - opens up a dialog box to search for the item
- Values saved in local data

0.2.0
- Ability to edit/delete items
- Gear summary (number of T1, T2, Ony, MC, BWL, free, total)
- Import from file (must be formatted properly)
- Export/report roster summary. Report contains:
    - A summary page (number of T1, T2, etc same as gear summary displayed)
    - Breakdown of all items by member by class

0.3.0
- Loot History by raid night
    - Add new night manually - specify date, instance, bosses downed
    - Edit/Delete raid nights
    - Links history to actual items displaying on characters
- Raid attendance tracker

0.4.0 (or 1.0.0, first true release)
- Automatic loot history tracking, as items are awarded
    - This needs to be enabled and items need to be editable in cases where loot master takes them and hands out as we go

Future features (nice to haves, maybe include some before 1.0.0)
- Loot rules per item, as a reference
- Compare players when counciling

repository: jamhands/lootwell

repo_name: jamhands/lootwell


text:
Define the transformation `flip-horiz`, which flips painters horizontally, and transformations that rotate painters counterclockwise by 180 degrees and 270 degrees.

```scheme
; In Drracket, transform-painter is a bit different from scheme
(define (flip-horizontal painter)
    ((transform-painter
        (make-vect 1 0)
        (make-vect 0 0)
        (make-vect 1 1)) painter))

(paint (flip-horizontal einstein))

(define (rotate-180 painter)
    ((transform-painter
        (make-vect 1 1)
        (make-vect 0 1)
        (make-vect 1 0)
        ) painter))

(paint (rotate-180 einstein))

(define (rotate-270 painter)
    ((transform-painter
        (make-vect 0 1)
        (make-vect 0 0)
        (make-vect 1 1)
        ) painter))

(paint (rotate-270 einstein))
```

repository: kenspirit/SICP

repo_name: kenspirit/SICP


text:
# Changelog for Windows DNS Cookbook

## 1.2.0

* Eliminated default nameservers
* Eliminated default suffix
* Organizational changes to increase supermarket quality

## 1.1.0

* Upgraded for Chef 14
* Added support for Windows 2008

## 1.0.1

* Fixed error when parsing empty DNS URL

## 1.0.0

* Initial public release


text:
---
title: Border's styles are not applied.
description: "Learn why the Border's styles may not be respected and how to overcome this problem in Telerik Reporting."
type: troubleshooting
page_title: Changing the Border's styles has no effect
slug: borders-style-is-not-applied
res_type: kb
---

## Environment

			Product
			Progress® Telerik® Reporting

## Description

In this article we will discuss possible solutions for when the Borders' styles set in the item's *Styles properties* are not respected.

## Possible Cause

The most common reason is that the **BorderStyle** and **BorderWidth** properties of the report item are set to conflicting values, for example:

````
BorderStyle: Solid

BorderWidth: 0px
````

This can produce unexpected result in some rendering formats.

## Solution

- To hide the border, set **BorderStyle=None**. Otherwise, the width of the border needs to be of value that is greater than 0.
- To set the width of the border, use **BorderStyle=Solid** (or all other options except "*None*") and specify the required value for *BorderWidth* property.

## See Also

* [Using Styles to Customize Reports]({%slug telerikreporting/designing-reports/styling-reports/using-styles-to-customize-reports%})
* [Style Inheritance and Overriding]({%slug telerikreporting/designing-reports/styling-reports/style-inheritance-and-overriding%})

repository: telerik/reporting-docs

gha_language: JavaScript

repo_name: telerik/reporting-docs


text:
[![Build Status](https://travis-ci.org/smakagon/eventify_pro.svg?branch=master)](https://travis-ci.org/smakagon/eventify_pro)

# EventifyPro

Client for [EventifyPro API](http://api.eventify.pro). Allows to publish events from Ruby-applications.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'eventify_pro'
```

And then execute:

    $ bundle install

Or install it yourself as:

    $ gem install eventify_pro

## Usage
___
### Getting Started:
This guide assumes you have created an account and obtained an API key from [EventifyPro](http://eventify.pro)

It's really easy to start publishing events with EventifyPro, just 2 lines of code:

```ruby
client = EventifyPro::Client.new(api_key: 'secret')
client.publish(type: 'OrderCreated', data: { order_id: 1, amount: 500 })
```

### Ruby On Rails
In a basic Ruby On Rails application you could create class under `lib` directory:

```ruby
# lib/eventify.rb

class Eventify
  def self.client
    @client ||= EventifyPro::Client.new(api_key: 'secret')
  end

  def self.publish(event_type, data)
    client.publish(type: event_type, data: data)
  end
end
```
Great, now to publish event from any place of your app use:

```ruby
Eventify.publish('UserSignedUp', { user_id: 1, first_name: 'John', last_name: 'Doe' })
```

* `type`: type of the event

* `data`: key and value pairs pertaining to the event

PS: Don't forget to enable loading of the `lib` directory in application.rb file:

```ruby
# config/application.rb

config.autoload_paths << Rails.root.join('lib')
```
___
#### Example:
```ruby
class OrdersController < ApplicationController
  def create
    @order = Order.new(params[:order])

    if @order.save
      Eventify.publish(type: 'OrderCreated', data: { order_id: @order.id, amount: @order.amount })
      redirect_to @order, notice: 'Post was successfully created.'
    else
      render :new
    end
  end
end
```
___
## Options

Example:
* `raise_error:`
  * By default, EventifyPro will swallow errors. It will return `true` or `false` depending on the result of publishing.
  * It's possible to pass `raise_errors: true`. In that case EventifyPro will throw EventifyPro::Error exception if something went wrong.

Example:
```ruby
eventify_client = EventifyPro::Client.new(api_key: 'secret', raise_errors: true)
begin
  eventify_client.publish(type: 'OrderCreated', data: { order_id: 1, amount: 1500 })
rescue EventifyPro::Error
  # exception handling
end
```

## License
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).

## Code of Conduct

Everyone interacting in the Eventify project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/smakagon/eventify/blob/master/CODE_OF_CONDUCT.md).