diffq


Namediffq JSON
Version 0.2.4 PyPI version JSON
download
home_pagehttps://github.com/facebookresearch/diffq
SummaryDifferentiable quantization framework for PyTorch.
upload_time2023-05-05 12:39:43
maintainer
docs_urlNone
authorAlexandre Défossez, Yossi Adi, Gabriel Synnaeve
requires_python>=3.7.0
licenseCreative Commons Attribution-NonCommercial 4.0 International
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# Differentiable Model Compression via Pseudo Quantization Noise
![linter badge](https://github.com/facebookresearch/diffq/workflows/linter/badge.svg)
![tests badge](https://github.com/facebookresearch/diffq/workflows/tests/badge.svg)
![cov badge](https://github.com/facebookresearch/diffq/workflows/cov%3E90%25/badge.svg)

DiffQ performs differentiable quantization using pseudo quantization noise.
It can automatically tune the number of bits used per weight or group of weights,
in order to achieve a given trade-off between model size and accuracy.

Go read [our paper][paper] for more details.


## What's up?

See [the changelog](CHANGELOG.md) for details on releases.

- 2022-08-24: v0.2.3: fixed a bug when loading old quantized states.
- 2021-11-25: version 0.2.2: adding support for torchscript.

## Requirements

DiffQ requires Python 3.7, and a reasonably recent version of PyTorch (1.7.1 ideally).
To install DiffQ, you can run from the root of the repository:

```
pip install .
```

You can also install directly from PyPI with `pip install diffq`.


## Usage

```python
import torch
from torch.nn import functional as F
import diffq
from diffq import DiffQuantizer

model = MyModel()
optim = ...  # The optimizer must be created before the quantizer
quantizer = DiffQuantizer(model)
quantizer.setup_optimizer(optim)

# Distributed data parallel must be created after DiffQuantizer!
dmodel = torch.distributed.DistributedDataParallel(...)

penalty = 1e-3
model.train()  # call model.eval() on eval to automatically use true quantized weights.
for batch in loader:
    ...
    optim.zero_grad()

    # The `penalty` parameter here will control the tradeoff between model size and model accuracy.
    loss = F.mse_loss(x, y) + penalty * quantizer.model_size()
    optim.step()

# To get the true model size with when doing proper bit packing.
print(f"Model is {quantizer.true_model_size():.1f} MB")

# When you want to dump your final model:
torch.save(quantizer.get_quantized_state(), "some_file.th")

# You can later load back the model with
model = MyModel()
diffq.restore_quantized_state(model, torch.load("some_file.th"))

# For DiffQ models, we support exporting the model to Torscript with optimal storage.
# Once loaded, the model will be stored in fp32 in memory (int8 support coming up).
from diffq.ts_export import export
export(quantizer, 'quantized.ts')
```

## Documentation

See the [API documentation][api] for detailed documentation.
We cover hereafter a few aspects.

### Quantizer object

A Quantizer is attached to a model at its creation.
All Quantizer objects provide the same basic capabilities:
- automatically switches to quantized weights on the forward if the model is in eval mode.
- quantizer-specific code on training forward (e.g. STE for UniformQuantizer with QAT,
 noise injection for DiffQ).
- provide access to the quantized model size and state.

### Quantized size and state

The method `quantizer.model_size()` provide a differentiable model size (for DiffQ),
  while `quantizer.true_model_size()` provide the true, optimally bit-packed, model size
  (non differentiable).
  With `quantizer.compressed_model_size()` you can get the model size using `gzip`.
  This can actually be larger than the true model size, and reveals interesting
  information on the entropy usage of a specific quantization method.

The bit-packed quantized state is obtained with `quantizer.get_quantized_state()` ,
and restored with `quantizer.restore_quantized_state()`.
Bit packing is optimized for speed and can suffer from some overhead
(in practice no more than 120B for Uniform and LSQ, and not more than 1kB for DiffQ).

If you do not have access to the original quantizer, for instance at inference time,
you can load the state with `diffq.restore_quantized_state(model, quantized_state)`.

### Quantizer and optimization

Some quantizer will add extra optimizable parameters (DiffQuantizer and LSQ).
Those parameters can require different optimizers or hyper-parameters than
the main model weights.
Typically, DiffQ bits parameters are always optimized with Adam.
For that reason, you should always create the main optimizer **before**
the quantizer. You can then setup the quantizer with this optimizer or another:

```python
model = MyModel(...)
opt = torch.optim.Adam(model.parameters())
quantizer = diffq.DiffQuantizer(model)
quantizer.setup_optimizer(opt, **optim_overrides)
```

This offers the freedom to use a separate hyper-params. For instance, `DiffQuantizer`
will always deactivate weight_decay for the bits parameters.

If the main optimizer is SGD, it is advised to have a second Adam optimizer
for the quantizer.

**Warning**: you must always wrap your model with `DistributedDataParallel`
after having created the quantizer, otherwise the quantizer parameters won't be optimized!

### TorchScript support

At the moment the TorchScript support is experimental. We support saving
the model with TorchScript to disk with optimal storage. Once loaded, the model
is stored in FP32 in memory. We are working towards adding support for int8
in memory. See the `diffq.ts_export.export` function in the API.

## Examples

We provide three examples in the `examples/` folder. One is for CIFAR-10/100,
using standard architecture such as Wide-ResNet, ResNet or MobileNet.
The second is based on the [DeiT][deit] visual transformer.
The third is a language modeling task on Wikitext-103, using [Fairseq][fairseq]

The DeiT and Fairseq examples are provided as a patch on the original codebase at a specific
commit. You can initialize the git submodule and apply the patches by running

```
make examples
```

For more details on each example, go checkout their specific READMEs:

- [CIFAR README](examples/cifar/README.md)
- [DeiT README](examples/DEIT_README.md)
- [Fairseq README](examples/FAIRSEQ_README.md)


## Installation for development

This will install the dependencies and a `diffq` in developer mode (changes to the files
will directly reflect), along with the dependencies to run unit tests.
```
pip install -e '.[dev]'
```

### Updating the patch based examples

In order to update the patches, first run `make examples` to properly initialize the sub repos. Then perform all the changes you want, commit them and run `make patches`. This will update the patches for each repo. Once this is done, and you checked that all the changes you did are properly included in the new patch files, you can run `make reset` (this will remove all your changes you did from the submodules, so do check the patch files before calling this) before calling `git add -u .; git commit -m "my changes"` and pushing.


### Test

You can run the unit tests with
```
make tests
```

## Citation

If you use this code or results in your paper, please cite our work as:

```
@article{defossez2021differentiable,
  title={Differentiable Model Compression via Pseudo Quantization Noise},
  author={D{\'e}fossez, Alexandre and Adi, Yossi and Synnaeve, Gabriel},
  journal={TMLR},
  year={2022}
}
```

## License

This repository is released under the CC-BY-NC 4.0. license as found in the
[LICENSE](LICENSE) file, except for the following parts that is under the MIT license.
The files `examples/cifar/src/mobilenet.py` and `examples/cifar/src/src/resnet.py` are taken from [kuangliu/pytorch-cifar](https://github.com/kuangliu/pytorch-cifar), released as MIT.
The file `examples/cifar/src/wide_resnet.py` is taken from [meliketoy/wide-resnet](https://github.com/meliketoy/wide-resnet.pytorch), released as MIT. See each file headers for the detailed license.

[api]: https://facebookresearch.github.io/diffq/diffq/index.html
[deit]: https://github.com/facebookresearch/deit
[fairseq]: https://github.com/pytorch/fairseq
[paper]: https://arxiv.org/abs/2104.09987

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/facebookresearch/diffq",
    "name": "diffq",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7.0",
    "maintainer_email": "",
    "keywords": "",
    "author": "Alexandre D\u00e9fossez, Yossi Adi, Gabriel Synnaeve",
    "author_email": "defossez@fb.com",
    "download_url": "https://files.pythonhosted.org/packages/5a/fd/4c58807bf855c5929ffa6da55f26dd6b9ae462a4193f5e09cc49fbbfd451/diffq-0.2.4.tar.gz",
    "platform": null,
    "description": "\n# Differentiable Model Compression via Pseudo Quantization Noise\n![linter badge](https://github.com/facebookresearch/diffq/workflows/linter/badge.svg)\n![tests badge](https://github.com/facebookresearch/diffq/workflows/tests/badge.svg)\n![cov badge](https://github.com/facebookresearch/diffq/workflows/cov%3E90%25/badge.svg)\n\nDiffQ performs differentiable quantization using pseudo quantization noise.\nIt can automatically tune the number of bits used per weight or group of weights,\nin order to achieve a given trade-off between model size and accuracy.\n\nGo read [our paper][paper] for more details.\n\n\n## What's up?\n\nSee [the changelog](CHANGELOG.md) for details on releases.\n\n- 2022-08-24: v0.2.3: fixed a bug when loading old quantized states.\n- 2021-11-25: version 0.2.2: adding support for torchscript.\n\n## Requirements\n\nDiffQ requires Python 3.7, and a reasonably recent version of PyTorch (1.7.1 ideally).\nTo install DiffQ, you can run from the root of the repository:\n\n```\npip install .\n```\n\nYou can also install directly from PyPI with `pip install diffq`.\n\n\n## Usage\n\n```python\nimport torch\nfrom torch.nn import functional as F\nimport diffq\nfrom diffq import DiffQuantizer\n\nmodel = MyModel()\noptim = ...  # The optimizer must be created before the quantizer\nquantizer = DiffQuantizer(model)\nquantizer.setup_optimizer(optim)\n\n# Distributed data parallel must be created after DiffQuantizer!\ndmodel = torch.distributed.DistributedDataParallel(...)\n\npenalty = 1e-3\nmodel.train()  # call model.eval() on eval to automatically use true quantized weights.\nfor batch in loader:\n    ...\n    optim.zero_grad()\n\n    # The `penalty` parameter here will control the tradeoff between model size and model accuracy.\n    loss = F.mse_loss(x, y) + penalty * quantizer.model_size()\n    optim.step()\n\n# To get the true model size with when doing proper bit packing.\nprint(f\"Model is {quantizer.true_model_size():.1f} MB\")\n\n# When you want to dump your final model:\ntorch.save(quantizer.get_quantized_state(), \"some_file.th\")\n\n# You can later load back the model with\nmodel = MyModel()\ndiffq.restore_quantized_state(model, torch.load(\"some_file.th\"))\n\n# For DiffQ models, we support exporting the model to Torscript with optimal storage.\n# Once loaded, the model will be stored in fp32 in memory (int8 support coming up).\nfrom diffq.ts_export import export\nexport(quantizer, 'quantized.ts')\n```\n\n## Documentation\n\nSee the [API documentation][api] for detailed documentation.\nWe cover hereafter a few aspects.\n\n### Quantizer object\n\nA Quantizer is attached to a model at its creation.\nAll Quantizer objects provide the same basic capabilities:\n- automatically switches to quantized weights on the forward if the model is in eval mode.\n- quantizer-specific code on training forward (e.g. STE for UniformQuantizer with QAT,\n noise injection for DiffQ).\n- provide access to the quantized model size and state.\n\n### Quantized size and state\n\nThe method `quantizer.model_size()` provide a differentiable model size (for DiffQ),\n  while `quantizer.true_model_size()` provide the true, optimally bit-packed, model size\n  (non differentiable).\n  With `quantizer.compressed_model_size()` you can get the model size using `gzip`.\n  This can actually be larger than the true model size, and reveals interesting\n  information on the entropy usage of a specific quantization method.\n\nThe bit-packed quantized state is obtained with `quantizer.get_quantized_state()` ,\nand restored with `quantizer.restore_quantized_state()`.\nBit packing is optimized for speed and can suffer from some overhead\n(in practice no more than 120B for Uniform and LSQ, and not more than 1kB for DiffQ).\n\nIf you do not have access to the original quantizer, for instance at inference time,\nyou can load the state with `diffq.restore_quantized_state(model, quantized_state)`.\n\n### Quantizer and optimization\n\nSome quantizer will add extra optimizable parameters (DiffQuantizer and LSQ).\nThose parameters can require different optimizers or hyper-parameters than\nthe main model weights.\nTypically, DiffQ bits parameters are always optimized with Adam.\nFor that reason, you should always create the main optimizer **before**\nthe quantizer. You can then setup the quantizer with this optimizer or another:\n\n```python\nmodel = MyModel(...)\nopt = torch.optim.Adam(model.parameters())\nquantizer = diffq.DiffQuantizer(model)\nquantizer.setup_optimizer(opt, **optim_overrides)\n```\n\nThis offers the freedom to use a separate hyper-params. For instance, `DiffQuantizer`\nwill always deactivate weight_decay for the bits parameters.\n\nIf the main optimizer is SGD, it is advised to have a second Adam optimizer\nfor the quantizer.\n\n**Warning**: you must always wrap your model with `DistributedDataParallel`\nafter having created the quantizer, otherwise the quantizer parameters won't be optimized!\n\n### TorchScript support\n\nAt the moment the TorchScript support is experimental. We support saving\nthe model with TorchScript to disk with optimal storage. Once loaded, the model\nis stored in FP32 in memory. We are working towards adding support for int8\nin memory. See the `diffq.ts_export.export` function in the API.\n\n## Examples\n\nWe provide three examples in the `examples/` folder. One is for CIFAR-10/100,\nusing standard architecture such as Wide-ResNet, ResNet or MobileNet.\nThe second is based on the [DeiT][deit] visual transformer.\nThe third is a language modeling task on Wikitext-103, using [Fairseq][fairseq]\n\nThe DeiT and Fairseq examples are provided as a patch on the original codebase at a specific\ncommit. You can initialize the git submodule and apply the patches by running\n\n```\nmake examples\n```\n\nFor more details on each example, go checkout their specific READMEs:\n\n- [CIFAR README](examples/cifar/README.md)\n- [DeiT README](examples/DEIT_README.md)\n- [Fairseq README](examples/FAIRSEQ_README.md)\n\n\n## Installation for development\n\nThis will install the dependencies and a `diffq` in developer mode (changes to the files\nwill directly reflect), along with the dependencies to run unit tests.\n```\npip install -e '.[dev]'\n```\n\n### Updating the patch based examples\n\nIn order to update the patches, first run `make examples` to properly initialize the sub repos. Then perform all the changes you want, commit them and run `make patches`. This will update the patches for each repo. Once this is done, and you checked that all the changes you did are properly included in the new patch files, you can run `make reset` (this will remove all your changes you did from the submodules, so do check the patch files before calling this) before calling `git add -u .; git commit -m \"my changes\"` and pushing.\n\n\n### Test\n\nYou can run the unit tests with\n```\nmake tests\n```\n\n## Citation\n\nIf you use this code or results in your paper, please cite our work as:\n\n```\n@article{defossez2021differentiable,\n  title={Differentiable Model Compression via Pseudo Quantization Noise},\n  author={D{\\'e}fossez, Alexandre and Adi, Yossi and Synnaeve, Gabriel},\n  journal={TMLR},\n  year={2022}\n}\n```\n\n## License\n\nThis repository is released under the CC-BY-NC 4.0. license as found in the\n[LICENSE](LICENSE) file, except for the following parts that is under the MIT license.\nThe files `examples/cifar/src/mobilenet.py` and `examples/cifar/src/src/resnet.py` are taken from [kuangliu/pytorch-cifar](https://github.com/kuangliu/pytorch-cifar), released as MIT.\nThe file `examples/cifar/src/wide_resnet.py` is taken from [meliketoy/wide-resnet](https://github.com/meliketoy/wide-resnet.pytorch), released as MIT. See each file headers for the detailed license.\n\n[api]: https://facebookresearch.github.io/diffq/diffq/index.html\n[deit]: https://github.com/facebookresearch/deit\n[fairseq]: https://github.com/pytorch/fairseq\n[paper]: https://arxiv.org/abs/2104.09987\n",
    "bugtrack_url": null,
    "license": "Creative Commons Attribution-NonCommercial 4.0 International",
    "summary": "Differentiable quantization framework for PyTorch.",
    "version": "0.2.4",
    "project_urls": {
        "Homepage": "https://github.com/facebookresearch/diffq"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b329592009a585a22f6313e2950b38173975c2be979b18fe4454679f67102cb8",
                "md5": "d1f358c026cd8e743d1b94abbea72523",
                "sha256": "3d8e6d6b882dd93568b41a7da9ff9657845ec08c82e71460544d0d04ed112320"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp310-cp310-macosx_10_9_universal2.whl",
            "has_sig": false,
            "md5_digest": "d1f358c026cd8e743d1b94abbea72523",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7.0",
            "size": 175814,
            "upload_time": "2023-05-05T12:38:53",
            "upload_time_iso_8601": "2023-05-05T12:38:53.920169Z",
            "url": "https://files.pythonhosted.org/packages/b3/29/592009a585a22f6313e2950b38173975c2be979b18fe4454679f67102cb8/diffq-0.2.4-cp310-cp310-macosx_10_9_universal2.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "992183da39abd8080e4aa5d211c6d17c3eb1b7e6e90b35bf98394ed648c5a039",
                "md5": "e21b0582b3bed3b136d65ccf34be47f8",
                "sha256": "15d5055ebfc629914689d66fcfa36f6d751fd45b4b2331ba0d3390604e2b40fa"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp310-cp310-macosx_10_9_x86_64.whl",
            "has_sig": false,
            "md5_digest": "e21b0582b3bed3b136d65ccf34be47f8",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7.0",
            "size": 106181,
            "upload_time": "2023-05-05T12:38:55",
            "upload_time_iso_8601": "2023-05-05T12:38:55.868067Z",
            "url": "https://files.pythonhosted.org/packages/99/21/83da39abd8080e4aa5d211c6d17c3eb1b7e6e90b35bf98394ed648c5a039/diffq-0.2.4-cp310-cp310-macosx_10_9_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4f45b6d26c9d4c64c1f6481fa8a85b9920951349a786bcfa2615241387a118dc",
                "md5": "0268ed191ed6dabb7ba77505b30dbd06",
                "sha256": "cf990911fc2c932e505df9958ce50417f182fe9178b2dbe329173b29e6521727"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp310-cp310-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "0268ed191ed6dabb7ba77505b30dbd06",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7.0",
            "size": 97366,
            "upload_time": "2023-05-05T12:38:57",
            "upload_time_iso_8601": "2023-05-05T12:38:57.642131Z",
            "url": "https://files.pythonhosted.org/packages/4f/45/b6d26c9d4c64c1f6481fa8a85b9920951349a786bcfa2615241387a118dc/diffq-0.2.4-cp310-cp310-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c95709ee34fd5756b5ebf96c63bcd82f4fabab4f1a95a350e491c1c8f92fdaad",
                "md5": "7e90fac73aba32638d44d6cdc80d47c4",
                "sha256": "d62ffd89498611dbf32cde417f5fc8d222f450085b06afb4e8764307906ab2ca"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl",
            "has_sig": false,
            "md5_digest": "7e90fac73aba32638d44d6cdc80d47c4",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7.0",
            "size": 401116,
            "upload_time": "2023-05-05T12:38:59",
            "upload_time_iso_8601": "2023-05-05T12:38:59.301955Z",
            "url": "https://files.pythonhosted.org/packages/c9/57/09ee34fd5756b5ebf96c63bcd82f4fabab4f1a95a350e491c1c8f92fdaad/diffq-0.2.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0e3b5ab58fda751ea353aa606260d78a9b58352aebf53d3a69183c593d14cd6d",
                "md5": "edd1d4f7d5cdf6573c8a0f978a708840",
                "sha256": "71a374573ec064227665208a5892d88032cb18736f68560d5522e0c48138ced1"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",
            "has_sig": false,
            "md5_digest": "edd1d4f7d5cdf6573c8a0f978a708840",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7.0",
            "size": 418777,
            "upload_time": "2023-05-05T12:39:01",
            "upload_time_iso_8601": "2023-05-05T12:39:01.169709Z",
            "url": "https://files.pythonhosted.org/packages/0e/3b/5ab58fda751ea353aa606260d78a9b58352aebf53d3a69183c593d14cd6d/diffq-0.2.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "98e55f6c7644b2b9585922ad116a605928db69320484a87dc236940a2e417172",
                "md5": "02749aa9e74238773b6d72ad31d38d5c",
                "sha256": "1480ea49785dfdcc793a3f20043aba430f510d51487063e3617020f5a2d2a753"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp310-cp310-win32.whl",
            "has_sig": false,
            "md5_digest": "02749aa9e74238773b6d72ad31d38d5c",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7.0",
            "size": 82208,
            "upload_time": "2023-05-05T12:39:02",
            "upload_time_iso_8601": "2023-05-05T12:39:02.864620Z",
            "url": "https://files.pythonhosted.org/packages/98/e5/5f6c7644b2b9585922ad116a605928db69320484a87dc236940a2e417172/diffq-0.2.4-cp310-cp310-win32.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ac9a60beef2ec7718daf4291064b7ae6e01e19496d6c8ade0002ba675cd67322",
                "md5": "470b93a2d6b4e94426c787aa3302568b",
                "sha256": "3467622841b15ece3d953fa42ad65f41703afe30e777bb910b96c89125174c8e"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp310-cp310-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "470b93a2d6b4e94426c787aa3302568b",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.7.0",
            "size": 91790,
            "upload_time": "2023-05-05T12:39:04",
            "upload_time_iso_8601": "2023-05-05T12:39:04.012565Z",
            "url": "https://files.pythonhosted.org/packages/ac/9a/60beef2ec7718daf4291064b7ae6e01e19496d6c8ade0002ba675cd67322/diffq-0.2.4-cp310-cp310-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2aeb7b8055f85850771211126ceb4c23e835f5d56f5d171a1ee88eb20500289d",
                "md5": "c304b83673c23010b8b4d2a3b7f473b5",
                "sha256": "3aef094383d39e12508ddf61c45a377986b2d4bac26ee553b6504fee10e2ff9d"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp37-cp37m-macosx_10_9_x86_64.whl",
            "has_sig": false,
            "md5_digest": "c304b83673c23010b8b4d2a3b7f473b5",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7.0",
            "size": 104479,
            "upload_time": "2023-05-05T12:39:05",
            "upload_time_iso_8601": "2023-05-05T12:39:05.757242Z",
            "url": "https://files.pythonhosted.org/packages/2a/eb/7b8055f85850771211126ceb4c23e835f5d56f5d171a1ee88eb20500289d/diffq-0.2.4-cp37-cp37m-macosx_10_9_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c4708581f5748e958b6c25d75a86def24e983dcdeb46c39775ff6d7fdcb9fd0f",
                "md5": "783d41888c3d2893e00c8b6cbd5ce9a6",
                "sha256": "0729231949ec74641709ad9b713ba127898735ba20ec8f44677d984d2ce1c3b9"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl",
            "has_sig": false,
            "md5_digest": "783d41888c3d2893e00c8b6cbd5ce9a6",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7.0",
            "size": 375980,
            "upload_time": "2023-05-05T12:39:08",
            "upload_time_iso_8601": "2023-05-05T12:39:08.101428Z",
            "url": "https://files.pythonhosted.org/packages/c4/70/8581f5748e958b6c25d75a86def24e983dcdeb46c39775ff6d7fdcb9fd0f/diffq-0.2.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5156b5e9725cba5d3e3c45ed7cd35e3f330413268159b592d3cae3bb45d2971c",
                "md5": "5d30f77a3f2c056bb5e27fcf0fcd21d7",
                "sha256": "d6779a81fcb8045d006a5f309c52a34e48fefb73db99232b4b1452a8829c083c"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",
            "has_sig": false,
            "md5_digest": "5d30f77a3f2c056bb5e27fcf0fcd21d7",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7.0",
            "size": 393768,
            "upload_time": "2023-05-05T12:39:09",
            "upload_time_iso_8601": "2023-05-05T12:39:09.969281Z",
            "url": "https://files.pythonhosted.org/packages/51/56/b5e9725cba5d3e3c45ed7cd35e3f330413268159b592d3cae3bb45d2971c/diffq-0.2.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "89ddeeea6caa7dc113bda4c13b85fd3cf2eff0f447d7657742dd077419b485b7",
                "md5": "d9c9773bcf3a4cf682efd82396d78e22",
                "sha256": "36f568bb1bbf75ac5601115e6253828c8c7b21a0501d7fcdc3b9545f80dc74f7"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp37-cp37m-win32.whl",
            "has_sig": false,
            "md5_digest": "d9c9773bcf3a4cf682efd82396d78e22",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7.0",
            "size": 81926,
            "upload_time": "2023-05-05T12:39:11",
            "upload_time_iso_8601": "2023-05-05T12:39:11.753163Z",
            "url": "https://files.pythonhosted.org/packages/89/dd/eeea6caa7dc113bda4c13b85fd3cf2eff0f447d7657742dd077419b485b7/diffq-0.2.4-cp37-cp37m-win32.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7b8182390c8c66f8cb4975c728ca3aae828d7f0a3d37adf5bcf8495f1efd4a59",
                "md5": "901a5f00fae86d0326cc1721ade47ba7",
                "sha256": "ee7f31d56f5131c2577dfa7bdb7d7284c5cce031fca0e30ac10d248b3e0e6841"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp37-cp37m-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "901a5f00fae86d0326cc1721ade47ba7",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.7.0",
            "size": 91926,
            "upload_time": "2023-05-05T12:39:12",
            "upload_time_iso_8601": "2023-05-05T12:39:12.929038Z",
            "url": "https://files.pythonhosted.org/packages/7b/81/82390c8c66f8cb4975c728ca3aae828d7f0a3d37adf5bcf8495f1efd4a59/diffq-0.2.4-cp37-cp37m-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b0baaf32f0228b14a72458b25280dec04b03655491132e8604afca9a9f6929c8",
                "md5": "8f4b1f26de5db342e7f96480c75cc425",
                "sha256": "de84917882a3def0d71548e5366813f7e25a7b110d2085fe0b0fa4c9877f5098"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp38-cp38-macosx_10_9_universal2.whl",
            "has_sig": false,
            "md5_digest": "8f4b1f26de5db342e7f96480c75cc425",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7.0",
            "size": 171139,
            "upload_time": "2023-05-05T12:39:15",
            "upload_time_iso_8601": "2023-05-05T12:39:15.103458Z",
            "url": "https://files.pythonhosted.org/packages/b0/ba/af32f0228b14a72458b25280dec04b03655491132e8604afca9a9f6929c8/diffq-0.2.4-cp38-cp38-macosx_10_9_universal2.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4a2417d7031906a03351d4d3e6cbb4d771b80f25eb1242a16b86a73d39f6a97e",
                "md5": "759361a5a5eeef1176e0263d8358983e",
                "sha256": "8937f15e45464fd899e9b3a6b1b57700c977367caf50a626f872dbb7883e3c1c"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp38-cp38-macosx_10_9_x86_64.whl",
            "has_sig": false,
            "md5_digest": "759361a5a5eeef1176e0263d8358983e",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7.0",
            "size": 103795,
            "upload_time": "2023-05-05T12:39:16",
            "upload_time_iso_8601": "2023-05-05T12:39:16.506679Z",
            "url": "https://files.pythonhosted.org/packages/4a/24/17d7031906a03351d4d3e6cbb4d771b80f25eb1242a16b86a73d39f6a97e/diffq-0.2.4-cp38-cp38-macosx_10_9_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "594575a6021a4a244c02f75c44132630441d0445846fda34389affdfe72daa15",
                "md5": "989b64e91aaf5c7153ec042ea7357ea7",
                "sha256": "8ff6ff92f3978770b0d2d355a5e553a554ea22732236cda9171c0683e5da5577"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp38-cp38-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "989b64e91aaf5c7153ec042ea7357ea7",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7.0",
            "size": 95136,
            "upload_time": "2023-05-05T12:39:19",
            "upload_time_iso_8601": "2023-05-05T12:39:19.117978Z",
            "url": "https://files.pythonhosted.org/packages/59/45/75a6021a4a244c02f75c44132630441d0445846fda34389affdfe72daa15/diffq-0.2.4-cp38-cp38-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7f24a3b46b2a3b764ea1680a7d0eadbbb3326a86de153e167a0a4043b40d71b0",
                "md5": "11ed46063259dcaa4ebc78b33b8a15c1",
                "sha256": "0b0cf50749d1a80fb74ee9e5135e08f06b519ab57f5b725bb374b2866412b725"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl",
            "has_sig": false,
            "md5_digest": "11ed46063259dcaa4ebc78b33b8a15c1",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7.0",
            "size": 428107,
            "upload_time": "2023-05-05T12:39:21",
            "upload_time_iso_8601": "2023-05-05T12:39:21.019364Z",
            "url": "https://files.pythonhosted.org/packages/7f/24/a3b46b2a3b764ea1680a7d0eadbbb3326a86de153e167a0a4043b40d71b0/diffq-0.2.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1e0a6151b12a53f7278eb0da3befcee0b9e0aa7bef2cbd7e7d14a7c76d526f75",
                "md5": "81c5a14a3ea671c78c4bb4cc358ceb9c",
                "sha256": "0381dedef3b88b4910eedfd894610ecac9affd689c2191c96694b70b3366dd27"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",
            "has_sig": false,
            "md5_digest": "81c5a14a3ea671c78c4bb4cc358ceb9c",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7.0",
            "size": 446643,
            "upload_time": "2023-05-05T12:39:22",
            "upload_time_iso_8601": "2023-05-05T12:39:22.671403Z",
            "url": "https://files.pythonhosted.org/packages/1e/0a/6151b12a53f7278eb0da3befcee0b9e0aa7bef2cbd7e7d14a7c76d526f75/diffq-0.2.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d77516097cea7c275615c094559aaec841a60fa25ac48b8c876d3134bb25aaeb",
                "md5": "1910c34f55d02c6e91d7d2f82dc73ae1",
                "sha256": "e793fed11642fdb4909efc0f87f2dbb52808dc5fa9865d7fcadb93ec5fd3aacd"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp38-cp38-win32.whl",
            "has_sig": false,
            "md5_digest": "1910c34f55d02c6e91d7d2f82dc73ae1",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7.0",
            "size": 83382,
            "upload_time": "2023-05-05T12:39:24",
            "upload_time_iso_8601": "2023-05-05T12:39:24.487942Z",
            "url": "https://files.pythonhosted.org/packages/d7/75/16097cea7c275615c094559aaec841a60fa25ac48b8c876d3134bb25aaeb/diffq-0.2.4-cp38-cp38-win32.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4ab52edadeb398560dedde227bcceeae70b05d9d3a5eec841172568f2bea12bf",
                "md5": "b46e3156d0aa425201ad1025c9b268e4",
                "sha256": "7566f823bda2f3f786dfea1ca2cfaa9663b854ccafcb1b185a4370690b628cf5"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp38-cp38-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "b46e3156d0aa425201ad1025c9b268e4",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.7.0",
            "size": 93086,
            "upload_time": "2023-05-05T12:39:26",
            "upload_time_iso_8601": "2023-05-05T12:39:26.170568Z",
            "url": "https://files.pythonhosted.org/packages/4a/b5/2edadeb398560dedde227bcceeae70b05d9d3a5eec841172568f2bea12bf/diffq-0.2.4-cp38-cp38-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cb2366b56a6ec679a24e8449368688674a6752a45962d93add1c7ff770574536",
                "md5": "7c0179a59e5ca42259232dc4a68da461",
                "sha256": "967a30e3a9da922d8705c3dbf44bb82d5b76a3ad49ecaa4c9450d97479fe8a31"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp39-cp39-macosx_10_9_universal2.whl",
            "has_sig": false,
            "md5_digest": "7c0179a59e5ca42259232dc4a68da461",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7.0",
            "size": 174950,
            "upload_time": "2023-05-05T12:39:27",
            "upload_time_iso_8601": "2023-05-05T12:39:27.501488Z",
            "url": "https://files.pythonhosted.org/packages/cb/23/66b56a6ec679a24e8449368688674a6752a45962d93add1c7ff770574536/diffq-0.2.4-cp39-cp39-macosx_10_9_universal2.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4fb927300827a7a4b1aaa9a59d4435dcf5767301dfe8394904134dcbab86cc8f",
                "md5": "13897ccc53ac54e5183bec47bf294420",
                "sha256": "78124e86f1e208830bfebe744c2321d92c65ba5d7e125d260ed418b4a2fa93df"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp39-cp39-macosx_10_9_x86_64.whl",
            "has_sig": false,
            "md5_digest": "13897ccc53ac54e5183bec47bf294420",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7.0",
            "size": 105953,
            "upload_time": "2023-05-05T12:39:28",
            "upload_time_iso_8601": "2023-05-05T12:39:28.940820Z",
            "url": "https://files.pythonhosted.org/packages/4f/b9/27300827a7a4b1aaa9a59d4435dcf5767301dfe8394904134dcbab86cc8f/diffq-0.2.4-cp39-cp39-macosx_10_9_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a975e898aaed1414c1fc4712090942913217762fa6c670b045cc07cbb91ed9e6",
                "md5": "89f11c2a6fc0dbbe6c03c3b76ece8377",
                "sha256": "ce966eb21bbb983e5bf5957c5832cad57d0968b7c5602da4065c3d1603ef8a95"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp39-cp39-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "89f11c2a6fc0dbbe6c03c3b76ece8377",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7.0",
            "size": 96660,
            "upload_time": "2023-05-05T12:39:31",
            "upload_time_iso_8601": "2023-05-05T12:39:31.122672Z",
            "url": "https://files.pythonhosted.org/packages/a9/75/e898aaed1414c1fc4712090942913217762fa6c670b045cc07cbb91ed9e6/diffq-0.2.4-cp39-cp39-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4f76857ec5bc72d035a69189a629624c0a04adebefbf39c0c30fa3c2dafeea76",
                "md5": "98e509792b3624aceba45339fbf28a53",
                "sha256": "02268472f1646cafe4fb3feaad9ac519f7e65d617871a58b56e71bc552fc8fb3"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl",
            "has_sig": false,
            "md5_digest": "98e509792b3624aceba45339fbf28a53",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7.0",
            "size": 409066,
            "upload_time": "2023-05-05T12:39:35",
            "upload_time_iso_8601": "2023-05-05T12:39:35.771485Z",
            "url": "https://files.pythonhosted.org/packages/4f/76/857ec5bc72d035a69189a629624c0a04adebefbf39c0c30fa3c2dafeea76/diffq-0.2.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8045ff8b779e9aeb653861fff9fceb65690a1b7e5c025d40cd930912731a65f7",
                "md5": "ead1288beecbe994429123aee3ccbda1",
                "sha256": "a5fc5cf4967d7cea065e75d2044824137ad08f1ccf7571d871cbf03bcf8809bd"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",
            "has_sig": false,
            "md5_digest": "ead1288beecbe994429123aee3ccbda1",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7.0",
            "size": 425490,
            "upload_time": "2023-05-05T12:39:37",
            "upload_time_iso_8601": "2023-05-05T12:39:37.005466Z",
            "url": "https://files.pythonhosted.org/packages/80/45/ff8b779e9aeb653861fff9fceb65690a1b7e5c025d40cd930912731a65f7/diffq-0.2.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "694a85492c979dde4f8762f2879dec5c4e9bc55aa5a82ca9d0caf467f962dea7",
                "md5": "3c6ca016c01162aba6935de7e8e80fd4",
                "sha256": "71575ca7202628ee1380a993aebee7e15c23ee12a96bc1a4dd1bff023aafdee2"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp39-cp39-win32.whl",
            "has_sig": false,
            "md5_digest": "3c6ca016c01162aba6935de7e8e80fd4",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7.0",
            "size": 83463,
            "upload_time": "2023-05-05T12:39:39",
            "upload_time_iso_8601": "2023-05-05T12:39:39.265998Z",
            "url": "https://files.pythonhosted.org/packages/69/4a/85492c979dde4f8762f2879dec5c4e9bc55aa5a82ca9d0caf467f962dea7/diffq-0.2.4-cp39-cp39-win32.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d348715aef982f49938063b181afe2aa7cd0998bcc6648ba79133dba2020ded7",
                "md5": "b030ff0892bd31c03a48a4760993ddec",
                "sha256": "9729121832c9abbbf4c443effe4e2c2952c48170d8c8255d79012d236c8dcd6d"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4-cp39-cp39-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "b030ff0892bd31c03a48a4760993ddec",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.7.0",
            "size": 93184,
            "upload_time": "2023-05-05T12:39:41",
            "upload_time_iso_8601": "2023-05-05T12:39:41.369074Z",
            "url": "https://files.pythonhosted.org/packages/d3/48/715aef982f49938063b181afe2aa7cd0998bcc6648ba79133dba2020ded7/diffq-0.2.4-cp39-cp39-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5afd4c58807bf855c5929ffa6da55f26dd6b9ae462a4193f5e09cc49fbbfd451",
                "md5": "a8994cc44b9310abf3cbd12a369add3b",
                "sha256": "049064861e974ebf00d0badab8b324c775037371419eda3150985b9d477b5bd2"
            },
            "downloads": -1,
            "filename": "diffq-0.2.4.tar.gz",
            "has_sig": false,
            "md5_digest": "a8994cc44b9310abf3cbd12a369add3b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7.0",
            "size": 157139,
            "upload_time": "2023-05-05T12:39:43",
            "upload_time_iso_8601": "2023-05-05T12:39:43.089590Z",
            "url": "https://files.pythonhosted.org/packages/5a/fd/4c58807bf855c5929ffa6da55f26dd6b9ae462a4193f5e09cc49fbbfd451/diffq-0.2.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-05 12:39:43",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "facebookresearch",
    "github_project": "diffq",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "diffq"
}
        
Elapsed time: 0.08608s