Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| # coding=utf-8 | |
| # Copyright 2018 The HuggingFace Inc. team. | |
| # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| """ Benchmarking the library on inference and training """ | |
| # If checking the tensors placement | |
| # tf.debugging.set_log_device_placement(True) | |
| import argparse | |
| import csv | |
| import timeit | |
| from time import time | |
| from typing import List | |
| from transformers import AutoConfig, AutoTokenizer, is_tf_available, is_torch_available | |
| if is_tf_available(): | |
| import tensorflow as tf | |
| from transformers import TFAutoModel | |
| if is_torch_available(): | |
| import torch | |
| from transformers import AutoModel | |
| input_text = """Bent over their instruments, three hundred Fertilizers were plunged, as | |
| the Director of Hatcheries and Conditioning entered the room, in the | |
| scarcely breathing silence, the absent-minded, soliloquizing hum or | |
| whistle, of absorbed concentration. A troop of newly arrived students, | |
| very young, pink and callow, followed nervously, rather abjectly, at the | |
| Director's heels. Each of them carried a notebook, in which, whenever | |
| the great man spoke, he desperately scribbled. Straight from the | |
| horse's mouth. It was a rare privilege. The D. H. C. for Central London | |
| always made a point of personally conducting his new students round | |
| the various departments. | |
| "Just to give you a general idea," he would explain to them. For of | |
| course some sort of general idea they must have, if they were to do | |
| their work intelligently-though as little of one, if they were to be good | |
| and happy members of society, as possible. For particulars, as every | |
| one knows, make for virtue and happiness; generalities are intellectu- | |
| ally necessary evils. Not philosophers but fret-sawyers and stamp col- | |
| lectors compose the backbone of society. | |
| "To-morrow," he would add, smiling at them with a slightly menacing | |
| geniality, "you'll be settling down to serious work. You won't have time | |
| for generalities. Meanwhile ..." | |
| Meanwhile, it was a privilege. Straight from the horse's mouth into the | |
| notebook. The boys scribbled like mad. | |
| Tall and rather thin but upright, the Director advanced into the room. | |
| He had a long chin and big rather prominent teeth, just covered, when | |
| he was not talking, by his full, floridly curved lips. Old, young? Thirty? | |
| Fifty? Fifty-five? It was hard to say. And anyhow the question didn't | |
| arise; in this year of stability, A. F. 632, it didn't occur to you to ask it. | |
| "I shall begin at the beginning," said the D.H.C. and the more zealous | |
| students recorded his intention in their notebooks: Begin at the begin- | |
| ning. "These," he waved his hand, "are the incubators." And opening | |
| an insulated door he showed them racks upon racks of numbered test- | |
| tubes. "The week's supply of ova. Kept," he explained, "at blood heat; | |
| whereas the male gametes," and here he opened another door, "they | |
| have to be kept at thirty-five instead of thirty-seven. Full blood heat | |
| sterilizes." Rams wrapped in theremogene beget no lambs. | |
| Still leaning against the incubators he gave them, while the pencils | |
| scurried illegibly across the pages, a brief description of the modern | |
| fertilizing process; spoke first, of course, of its surgical introduc- | |
| tion-"the operation undergone voluntarily for the good of Society, not | |
| to mention the fact that it carries a bonus amounting to six months' | |
| salary"; continued with some account of the technique for preserving | |
| the excised ovary alive and actively developing; passed on to a consid- | |
| eration of optimum temperature, salinity, viscosity; referred to the liq- | |
| uor in which the detached and ripened eggs were kept; and, leading | |
| his charges to the work tables, actually showed them how this liquor | |
| was drawn off from the test-tubes; how it was let out drop by drop | |
| onto the specially warmed slides of the microscopes; how the eggs | |
| which it contained were inspected for abnormalities, counted and | |
| transferred to a porous receptacle; how (and he now took them to | |
| watch the operation) this receptacle was immersed in a warm bouillon | |
| containing free-swimming spermatozoa-at a minimum concentration | |
| of one hundred thousand per cubic centimetre, he insisted; and how, | |
| after ten minutes, the container was lifted out of the liquor and its | |
| contents re-examined; how, if any of the eggs remained unfertilized, it | |
| was again immersed, and, if necessary, yet again; how the fertilized | |
| ova went back to the incubators; where the Alphas and Betas re- | |
| mained until definitely bottled; while the Gammas, Deltas and Epsilons | |
| were brought out again, after only thirty-six hours, to undergo Bo- | |
| kanovsky's Process. | |
| "Bokanovsky's Process," repeated the Director, and the students un- | |
| derlined the words in their little notebooks. | |
| One egg, one embryo, one adult-normality. But a bokanovskified egg | |
| will bud, will proliferate, will divide. From eight to ninety-six buds, and | |
| every bud will grow into a perfectly formed embryo, and every embryo | |
| into a full-sized adult. Making ninety-six human beings grow where | |
| only one grew before. Progress. | |
| "Essentially," the D.H.C. concluded, "bokanovskification consists of a | |
| series of arrests of development. We check the normal growth and, | |
| paradoxically enough, the egg responds by budding." | |
| Responds by budding. The pencils were busy. | |
| He pointed. On a very slowly moving band a rack-full of test-tubes was | |
| entering a large metal box, another, rack-full was emerging. Machinery | |
| faintly purred. It took eight minutes for the tubes to go through, he | |
| told them. Eight minutes of hard X-rays being about as much as an | |
| egg can stand. A few died; of the rest, the least susceptible divided | |
| into two; most put out four buds; some eight; all were returned to the | |
| incubators, where the buds began to develop; then, after two days, | |
| were suddenly chilled, chilled and checked. Two, four, eight, the buds | |
| in their turn budded; and having budded were dosed almost to death | |
| with alcohol; consequently burgeoned again and having budded-bud | |
| out of bud out of bud-were thereafter-further arrest being generally | |
| fatal-left to develop in peace. By which time the original egg was in a | |
| fair way to becoming anything from eight to ninety-six embryos- a | |
| prodigious improvement, you will agree, on nature. Identical twins-but | |
| not in piddling twos and threes as in the old viviparous days, when an | |
| egg would sometimes accidentally divide; actually by dozens, by | |
| scores at a time. | |
| "Scores," the Director repeated and flung out his arms, as though he | |
| were distributing largesse. "Scores." | |
| But one of the students was fool enough to ask where the advantage | |
| lay. | |
| "My good boy!" The Director wheeled sharply round on him. "Can't you | |
| see? Can't you see?" He raised a hand; his expression was solemn. | |
| "Bokanovsky's Process is one of the major instruments of social stabil- | |
| ity!" | |
| Major instruments of social stability. | |
| Standard men and women; in uniform batches. The whole of a small | |
| factory staffed with the products of a single bokanovskified egg. | |
| "Ninety-six identical twins working ninety-six identical machines!" The | |
| voice was almost tremulous with enthusiasm. "You really know where | |
| you are. For the first time in history." He quoted the planetary motto. | |
| "Community, Identity, Stability." Grand words. "If we could bo- | |
| kanovskify indefinitely the whole problem would be solved." | |
| Solved by standard Gammas, unvarying Deltas, uniform Epsilons. Mil- | |
| lions of identical twins. The principle of mass production at last applied | |
| to biology. | |
| "But, alas," the Director shook his head, "we can't bokanovskify indefi- | |
| nitely." | |
| Ninety-six seemed to be the limit; seventy-two a good average. From | |
| the same ovary and with gametes of the same male to manufacture as | |
| many batches of identical twins as possible-that was the best (sadly a | |
| second best) that they could do. And even that was difficult. | |
| "For in nature it takes thirty years for two hundred eggs to reach ma- | |
| turity. But our business is to stabilize the population at this moment, | |
| here and now. Dribbling out twins over a quarter of a century-what | |
| would be the use of that?" | |
| Obviously, no use at all. But Podsnap's Technique had immensely ac- | |
| celerated the process of ripening. They could make sure of at least a | |
| hundred and fifty mature eggs within two years. Fertilize and bo- | |
| kanovskify-in other words, multiply by seventy-two-and you get an | |
| average of nearly eleven thousand brothers and sisters in a hundred | |
| and fifty batches of identical twins, all within two years of the same | |
| age. | |
| "And in exceptional cases we can make one ovary yield us over fifteen | |
| thousand adult individuals." | |
| Beckoning to a fair-haired, ruddy young man who happened to be | |
| passing at the moment. "Mr. Foster," he called. The ruddy young man | |
| approached. "Can you tell us the record for a single ovary, Mr. Foster?" | |
| "Sixteen thousand and twelve in this Centre," Mr. Foster replied with- | |
| out hesitation. He spoke very quickly, had a vivacious blue eye, and | |
| took an evident pleasure in quoting figures. "Sixteen thousand and | |
| twelve; in one hundred and eighty-nine batches of identicals. But of | |
| course they've done much better," he rattled on, "in some of the tropi- | |
| cal Centres. Singapore has often produced over sixteen thousand five | |
| hundred; and Mombasa has actually touched the seventeen thousand | |
| mark. But then they have unfair advantages. You should see the way a | |
| negro ovary responds to pituitary! It's quite astonishing, when you're | |
| used to working with European material. Still," he added, with a laugh | |
| (but the light of combat was in his eyes and the lift of his chin was | |
| challenging), "still, we mean to beat them if we can. I'm working on a | |
| wonderful Delta-Minus ovary at this moment. Only just eighteen | |
| months old. Over twelve thousand seven hundred children already, ei- | |
| ther decanted or in embryo. And still going strong. We'll beat them | |
| yet." | |
| "That's the spirit I like!" cried the Director, and clapped Mr. Foster on | |
| the shoulder. "Come along with us, and give these boys the benefit of | |
| your expert knowledge." | |
| Mr. Foster smiled modestly. "With pleasure." They went. | |
| In the Bottling Room all was harmonious bustle and ordered activity. | |
| Flaps of fresh sow's peritoneum ready cut to the proper size came | |
| shooting up in little lifts from the Organ Store in the sub-basement. | |
| Whizz and then, click! the lift-hatches hew open; the bottle-liner had | |
| only to reach out a hand, take the flap, insert, smooth-down, and be- | |
| fore the lined bottle had had time to travel out of reach along the end- | |
| less band, whizz, click! another flap of peritoneum had shot up from | |
| the depths, ready to be slipped into yet another bottle, the next of that | |
| slow interminable procession on the band. | |
| Next to the Liners stood the Matriculators. The procession advanced; | |
| one by one the eggs were transferred from their test-tubes to the | |
| larger containers; deftly the peritoneal lining was slit, the morula | |
| dropped into place, the saline solution poured in ... and already the | |
| bottle had passed, and it was the turn of the labellers. Heredity, date | |
| of fertilization, membership of Bokanovsky Group-details were trans- | |
| ferred from test-tube to bottle. No longer anonymous, but named, | |
| identified, the procession marched slowly on; on through an opening in | |
| the wall, slowly on into the Social Predestination Room. | |
| "Eighty-eight cubic metres of card-index," said Mr. Foster with relish, | |
| as they entered.""" | |
| def create_setup_and_compute( | |
| model_names: List[str], | |
| gpu: bool = True, | |
| tensorflow: bool = False, | |
| average_over: int = 3, | |
| torchscript: bool = False, | |
| xla: bool = False, | |
| amp: bool = False, | |
| fp16: bool = False, | |
| save_to_csv: bool = False, | |
| csv_filename: str = f"results_{round(time())}.csv", | |
| ): | |
| if xla: | |
| tf.config.optimizer.set_jit(True) | |
| if amp: | |
| tf.config.optimizer.set_experimental_options({"auto_mixed_precision": True}) | |
| if tensorflow: | |
| dictionary = {model_name: {} for model_name in model_names} | |
| results = _compute_tensorflow(model_names, dictionary, average_over, amp) | |
| else: | |
| device = "cuda" if (gpu and torch.cuda.is_available()) else "cpu" | |
| dictionary = {model_name: {} for model_name in model_names} | |
| results = _compute_pytorch(model_names, dictionary, average_over, device, torchscript, fp16) | |
| print("=========== RESULTS ===========") | |
| for model_name in model_names: | |
| print("\t" + f"======= MODEL CHECKPOINT: {model_name} =======") | |
| for batch_size in results[model_name]["bs"]: | |
| print("\t\t" + f"===== BATCH SIZE: {batch_size} =====") | |
| for slice_size in results[model_name]["ss"]: | |
| result = results[model_name]["results"][batch_size][slice_size] | |
| if isinstance(result, str): | |
| print(f"\t\t{model_name}/{batch_size}/{slice_size}: " f"{result}") | |
| else: | |
| print(f"\t\t{model_name}/{batch_size}/{slice_size}: " f"{(round(1000 * result) / 1000)}" f"s") | |
| if save_to_csv: | |
| with open(csv_filename, mode="w") as csv_file: | |
| fieldnames = [ | |
| "model", | |
| "1x8", | |
| "1x64", | |
| "1x128", | |
| "1x256", | |
| "1x512", | |
| "1x1024", | |
| "2x8", | |
| "2x64", | |
| "2x128", | |
| "2x256", | |
| "2x512", | |
| "2x1024", | |
| "4x8", | |
| "4x64", | |
| "4x128", | |
| "4x256", | |
| "4x512", | |
| "4x1024", | |
| "8x8", | |
| "8x64", | |
| "8x128", | |
| "8x256", | |
| "8x512", | |
| "8x1024", | |
| ] | |
| writer = csv.DictWriter(csv_file, fieldnames=fieldnames) | |
| writer.writeheader() | |
| for model_name in model_names: | |
| model_results = { | |
| f"{bs}x{ss}": results[model_name]["results"][bs][ss] | |
| for bs in results[model_name]["results"] | |
| for ss in results[model_name]["results"][bs] | |
| } | |
| writer.writerow({"model": model_name, **model_results}) | |
| def _compute_pytorch(model_names, dictionary, average_over, device, torchscript, fp16): | |
| for c, model_name in enumerate(model_names): | |
| print(f"{c + 1} / {len(model_names)}") | |
| config = AutoConfig.from_pretrained(model_name, torchscript=torchscript) | |
| model = AutoModel.from_pretrained(model_name, config=config) | |
| tokenizer = AutoTokenizer.from_pretrained(model_name) | |
| tokenized_sequence = tokenizer.encode(input_text, add_special_tokens=False) | |
| max_input_size = tokenizer.max_model_input_sizes[model_name] | |
| batch_sizes = [1, 2, 4, 8] | |
| slice_sizes = [8, 64, 128, 256, 512, 1024] | |
| dictionary[model_name] = {"bs": batch_sizes, "ss": slice_sizes, "results": {}} | |
| dictionary[model_name]["results"] = {i: {} for i in batch_sizes} | |
| for batch_size in batch_sizes: | |
| if fp16: | |
| model.half() | |
| model.to(device) | |
| model.eval() | |
| for slice_size in slice_sizes: | |
| if max_input_size is not None and slice_size > max_input_size: | |
| dictionary[model_name]["results"][batch_size][slice_size] = "N/A" | |
| else: | |
| sequence = torch.tensor(tokenized_sequence[:slice_size], device=device).repeat(batch_size, 1) | |
| try: | |
| if torchscript: | |
| print("Tracing model with sequence size", sequence.shape) | |
| inference = torch.jit.trace(model, sequence) | |
| inference(sequence) | |
| else: | |
| inference = model | |
| inference(sequence) | |
| print("Going through model with sequence of shape", sequence.shape) | |
| runtimes = timeit.repeat(lambda: inference(sequence), repeat=average_over, number=3) | |
| average_time = sum(runtimes) / float(len(runtimes)) / 3.0 | |
| dictionary[model_name]["results"][batch_size][slice_size] = average_time | |
| except RuntimeError as e: | |
| print("Doesn't fit on GPU.", e) | |
| torch.cuda.empty_cache() | |
| dictionary[model_name]["results"][batch_size][slice_size] = "N/A" | |
| return dictionary | |
| def _compute_tensorflow(model_names, dictionary, average_over, amp): | |
| for c, model_name in enumerate(model_names): | |
| print(f"{c + 1} / {len(model_names)}") | |
| config = AutoConfig.from_pretrained(model_name) | |
| model = TFAutoModel.from_pretrained(model_name, config=config) | |
| tokenizer = AutoTokenizer.from_pretrained(model_name) | |
| tokenized_sequence = tokenizer.encode(input_text, add_special_tokens=False) | |
| max_input_size = tokenizer.max_model_input_sizes[model_name] | |
| batch_sizes = [1, 2, 4, 8] | |
| slice_sizes = [8, 64, 128, 256, 512, 1024] | |
| dictionary[model_name] = {"bs": batch_sizes, "ss": slice_sizes, "results": {}} | |
| dictionary[model_name]["results"] = {i: {} for i in batch_sizes} | |
| print("Using model", model) | |
| def inference(inputs): | |
| return model(inputs) | |
| for batch_size in batch_sizes: | |
| for slice_size in slice_sizes: | |
| if max_input_size is not None and slice_size > max_input_size: | |
| dictionary[model_name]["results"][batch_size][slice_size] = "N/A" | |
| else: | |
| sequence = tf.stack( | |
| [tf.squeeze(tf.constant(tokenized_sequence[:slice_size])[None, :])] * batch_size | |
| ) | |
| try: | |
| print("Going through model with sequence of shape", sequence.shape) | |
| # To make sure that the model is traced + that the tensors are on the appropriate device | |
| inference(sequence) | |
| runtimes = timeit.repeat(lambda: inference(sequence), repeat=average_over, number=3) | |
| average_time = sum(runtimes) / float(len(runtimes)) / 3.0 | |
| dictionary[model_name]["results"][batch_size][slice_size] = average_time | |
| except tf.errors.ResourceExhaustedError as e: | |
| print("Doesn't fit on GPU.", e) | |
| torch.cuda.empty_cache() | |
| dictionary[model_name]["results"][batch_size][slice_size] = "N/A" | |
| return dictionary | |
| def main(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument( | |
| "--models", | |
| required=False, | |
| type=str, | |
| default="all", | |
| help="Model checkpoints to be provided " | |
| "to the AutoModel classes. Leave " | |
| "blank to benchmark the base version " | |
| "of all available model " | |
| "architectures.", | |
| ) | |
| parser.add_argument( | |
| "--torch", required=False, action="store_true", help="Benchmark the Pytorch version of the " "models" | |
| ) | |
| parser.add_argument( | |
| "--torch_cuda", required=False, action="store_true", help="Pytorch only: run on available " "cuda devices" | |
| ) | |
| parser.add_argument( | |
| "--torchscript", | |
| required=False, | |
| action="store_true", | |
| help="Pytorch only: trace the models " "using torchscript", | |
| ) | |
| parser.add_argument( | |
| "--tensorflow", | |
| required=False, | |
| action="store_true", | |
| help="Benchmark the TensorFlow version " | |
| "of the models. Will run on GPU if " | |
| "the correct dependencies are " | |
| "installed", | |
| ) | |
| parser.add_argument("--xla", required=False, action="store_true", help="TensorFlow only: use XLA acceleration.") | |
| parser.add_argument( | |
| "--amp", | |
| required=False, | |
| action="store_true", | |
| help="TensorFlow only: use automatic mixed precision acceleration.", | |
| ) | |
| parser.add_argument( | |
| "--fp16", required=False, action="store_true", help="PyTorch only: use FP16 to accelerate inference." | |
| ) | |
| parser.add_argument( | |
| "--keras_predict", | |
| required=False, | |
| action="store_true", | |
| help="Whether to use model.predict " "instead of model() to do a " "forward pass.", | |
| ) | |
| parser.add_argument("--save_to_csv", required=False, action="store_true", help="Save to a CSV file.") | |
| parser.add_argument( | |
| "--csv_filename", required=False, default=None, help="CSV filename used if saving results to csv." | |
| ) | |
| parser.add_argument( | |
| "--average_over", required=False, default=30, type=int, help="Times an experiment will be run." | |
| ) | |
| args = parser.parse_args() | |
| if args.models == "all": | |
| args.models = [ | |
| "gpt2", | |
| "bert-base-cased", | |
| "xlnet-base-cased", | |
| "xlm-mlm-en-2048", | |
| "transfo-xl-wt103", | |
| "openai-gpt", | |
| "distilbert-base-uncased", | |
| "distilgpt2", | |
| "roberta-base", | |
| "ctrl", | |
| ] | |
| else: | |
| args.models = args.models.split() | |
| print("Running with arguments", args) | |
| if args.torch: | |
| if is_torch_available(): | |
| create_setup_and_compute( | |
| model_names=args.models, | |
| tensorflow=False, | |
| gpu=args.torch_cuda, | |
| torchscript=args.torchscript, | |
| fp16=args.fp16, | |
| save_to_csv=args.save_to_csv, | |
| csv_filename=args.csv_filename, | |
| average_over=args.average_over, | |
| ) | |
| else: | |
| raise ImportError("Trying to run a PyTorch benchmark but PyTorch was not found in the environment.") | |
| if args.tensorflow: | |
| if is_tf_available(): | |
| create_setup_and_compute( | |
| model_names=args.models, | |
| tensorflow=True, | |
| xla=args.xla, | |
| amp=args.amp, | |
| save_to_csv=args.save_to_csv, | |
| csv_filename=args.csv_filename, | |
| average_over=args.average_over, | |
| ) | |
| else: | |
| raise ImportError("Trying to run a TensorFlow benchmark but TensorFlow was not found in the environment.") | |
| if __name__ == "__main__": | |
| main() | |