From d746ea6278b3419986c1e6a8359b236a47ab7abc Mon Sep 17 00:00:00 2001 From: Adriane Boyd Date: Tue, 9 Mar 2021 15:35:21 +0100 Subject: [PATCH] Add warning about GPU selection in Jupyter notebooks (#7075) * Initial warning * Update check * Redo edit * Move jupyter warning to helper method * Add link with details to warnings --- spacy/errors.py | 5 +++++ spacy/language.py | 5 +++++ spacy/util.py | 12 ++++++++++++ website/docs/api/top-level.md | 24 ++++++++++++++++++++++++ website/docs/usage/v3.md | 12 ++++++++++++ 5 files changed, 58 insertions(+) diff --git a/spacy/errors.py b/spacy/errors.py index e50a658d8..4f9e90b57 100644 --- a/spacy/errors.py +++ b/spacy/errors.py @@ -147,6 +147,11 @@ class Warnings: "will be included in the results. For better results, token " "patterns should return matches that are each exactly one token " "long.") + W111 = ("Jupyter notebook detected: if using `prefer_gpu()` or " + "`require_gpu()`, include it in the same cell right before " + "`spacy.load()` to ensure that the model is loaded on the correct " + "device. More information: " + "http://spacy.io/usage/v3#jupyter-notebook-gpu") @add_codes diff --git a/spacy/language.py b/spacy/language.py index 5741ef97c..871dfafaa 100644 --- a/spacy/language.py +++ b/spacy/language.py @@ -22,6 +22,7 @@ from .training.initialize import init_vocab, init_tok2vec from .scorer import Scorer from .util import registry, SimpleFrozenList, _pipe, raise_error from .util import SimpleFrozenDict, combine_score_weights, CONFIG_SECTION_ORDER +from .util import warn_if_jupyter_cupy from .lang.tokenizer_exceptions import URL_MATCH, BASE_EXCEPTIONS from .lang.punctuation import TOKENIZER_PREFIXES, TOKENIZER_SUFFIXES from .lang.punctuation import TOKENIZER_INFIXES @@ -1622,6 +1623,10 @@ class Language: or lang_cls is not cls ): raise ValueError(Errors.E943.format(value=type(lang_cls))) + + # Warn about require_gpu usage in jupyter notebook + warn_if_jupyter_cupy() + # Note that we don't load vectors here, instead they get loaded explicitly # inside stuff like the spacy train function. If we loaded them here, # then we would load them twice at runtime: once when we make from config, diff --git a/spacy/util.py b/spacy/util.py index bcb51fe7d..4b82eea8d 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -1500,3 +1500,15 @@ def raise_error(proc_name, proc, docs, e): def ignore_error(proc_name, proc, docs, e): pass + + +def warn_if_jupyter_cupy(): + """Warn about require_gpu if a jupyter notebook + cupy + mismatched + contextvars vs. thread ops are detected + """ + if is_in_jupyter(): + from thinc.backends.cupy_ops import CupyOps + if CupyOps.xp is not None: + from thinc.backends import contextvars_eq_thread_ops + if not contextvars_eq_thread_ops(): + warnings.warn(Warnings.W111) diff --git a/website/docs/api/top-level.md b/website/docs/api/top-level.md index 37f619f3e..e1d81a5b5 100644 --- a/website/docs/api/top-level.md +++ b/website/docs/api/top-level.md @@ -138,6 +138,14 @@ data has already been allocated on CPU, it will not be moved. Ideally, this function should be called right after importing spaCy and _before_ loading any pipelines. + + +In a Jupyter notebook, run `prefer_gpu()` in the same cell as `spacy.load()` +to ensure that the model is loaded on the correct device. See [more +details](/usage/v3#jupyter-notebook-gpu). + + + > #### Example > > ```python @@ -158,6 +166,14 @@ if no GPU is available. If data has already been allocated on CPU, it will not be moved. Ideally, this function should be called right after importing spaCy and _before_ loading any pipelines. + + +In a Jupyter notebook, run `require_gpu()` in the same cell as `spacy.load()` +to ensure that the model is loaded on the correct device. See [more +details](/usage/v3#jupyter-notebook-gpu). + + + > #### Example > > ```python @@ -177,6 +193,14 @@ Allocate data and perform operations on CPU. If data has already been allocated on GPU, it will not be moved. Ideally, this function should be called right after importing spaCy and _before_ loading any pipelines. + + +In a Jupyter notebook, run `require_cpu()` in the same cell as `spacy.load()` +to ensure that the model is loaded on the correct device. See [more +details](/usage/v3#jupyter-notebook-gpu). + + + > #### Example > > ```python diff --git a/website/docs/usage/v3.md b/website/docs/usage/v3.md index 21e99ffc2..847d4a327 100644 --- a/website/docs/usage/v3.md +++ b/website/docs/usage/v3.md @@ -1179,3 +1179,15 @@ This means that spaCy knows how to initialize `my_component`, even if your package isn't imported. + +#### Using GPUs in Jupyter notebooks {#jupyter-notebook-gpu} + +In Jupyter notebooks, run [`prefer_gpu`](/api/top-level#spacy.prefer_gpu), +[`require_gpu`](/api/top-level#spacy.require_gpu) or +[`require_cpu`](/api/top-level#spacy.require_cpu) in the same cell as +[`spacy.load`](/api/top-level#spacy.load) to ensure that the model is loaded on the correct device. + +Due to a bug related to `contextvars` (see the [bug +report](https://github.com/ipython/ipython/issues/11565)), the GPU settings may +not be preserved correctly across cells, resulting in models being loaded on +the wrong device or only partially on GPU.