From 41c1ae528d34493b43f808208aee024ceea052e7 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 2 Aug 2025 12:08:01 +0200 Subject: Speed up multiples generation. Make each worker write in a tempfile. Removes the unpickling bottleneck of the parent that is scheduling the workers. --- analysis/scalarmults/common.py | 6 + analysis/scalarmults/simulate.ipynb | 559 ++++++++++++++++++++++++++++++++++-- 2 files changed, 540 insertions(+), 25 deletions(-) diff --git a/analysis/scalarmults/common.py b/analysis/scalarmults/common.py index c2369f6..f92aac5 100644 --- a/analysis/scalarmults/common.py +++ b/analysis/scalarmults/common.py @@ -176,6 +176,12 @@ class MultIdent: error_model = f"+{self.error_model}" if self.error_model is not None else "" return f"{name}{args}{kwargs}{countermeasure}{error_model}" + def __getstate__(self): + state = self.__dict__.copy() + # Remove cached properties + state.pop("partial", None) + return state + def __lt__(self, other): if not isinstance(other, MultIdent): return NotImplemented diff --git a/analysis/scalarmults/simulate.ipynb b/analysis/scalarmults/simulate.ipynb index 4c06b10..dae8d06 100644 --- a/analysis/scalarmults/simulate.ipynb +++ b/analysis/scalarmults/simulate.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "b4386513-cc14-434b-a748-2863f8657452", "metadata": {}, "outputs": [], @@ -18,10 +18,11 @@ "import itertools\n", "import gc\n", "import glob\n", + "import hashlib\n", "import pickle\n", "import random\n", "import re\n", - "import hashlib\n", + "import tempfile\n", "\n", "import warnings\n", "warnings.filterwarnings(\n", @@ -61,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "3463a7bd-34d8-458b-8ceb-dddf99de21dc", "metadata": {}, "outputs": [], @@ -78,10 +79,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "170c11fc-86cf-4eb1-bf4e-b2e44b2d7ac5", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scalar multipliers considered: 65\n", + "Scalar multipliers (with a single countermeasure) considered: 390\n", + "Error models considered: 32\n", + "Total configurations considered: 12480\n" + ] + } + ], "source": [ "nmults = len(all_mults)\n", "nmults_ctr = len(all_mults_with_ctr)\n", @@ -104,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "4d5c7f10-618f-4612-b594-81d1607b0d1d", "metadata": {}, "outputs": [], @@ -115,15 +127,15 @@ "use_init = True\n", "use_multiply = True\n", "params = get_params(category, curve, \"projective\")\n", - "num_workers = 20\n", + "num_workers = 30\n", "bits = params.order.bit_length()\n", - "samples = 100\n", + "samples = 1000\n", "selected_mults = all_mults" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "07bc266d-35eb-4f6d-bdba-e9f6f66827f1", "metadata": {}, "outputs": [], @@ -154,7 +166,42 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, + "id": "6f3e9ffa-19e8-46b2-a6ad-1d318d5c8e17", + "metadata": {}, + "outputs": [], + "source": [ + "def simulate_multiples_direct(mult: MultIdent,\n", + " params: DomainParameters,\n", + " bits: int,\n", + " fname: str,\n", + " samples: int = 100,\n", + " use_init: bool = True,\n", + " use_multiply: bool = True,\n", + " seed: bytes | None = None) -> MultResults:\n", + " results = []\n", + " if seed is not None:\n", + " random.seed(seed)\n", + "\n", + " # If no countermeasure is used, we have fully random scalars.\n", + " # Otherwise, fix one per chunk.\n", + " if mult.countermeasure is None:\n", + " scalars = [random.randint(1, 2**bits) for _ in range(samples)]\n", + " else:\n", + " one = random.randint(1, 2**bits)\n", + " scalars = [one for _ in range(samples)]\n", + "\n", + " for scalar in scalars:\n", + " results.append(multiple_graph(scalar, params, mult.klass, mult.partial, use_init, use_multiply))\n", + " result = MultResults(results, samples)\n", + " with open(fname, \"wb\") as f:\n", + " pickle.dump((mult, result), f)\n", + " return fname" + ] + }, + { + "cell_type": "code", + "execution_count": 7, "id": "64799c16-8113-4eff-81de-6a3e547eb5c5", "metadata": {}, "outputs": [], @@ -181,7 +228,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "ac630a08-4120-41cf-b3bb-1827ef469542", "metadata": {}, "outputs": [], @@ -220,28 +267,439 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "84359084-4116-436c-92cd-d43fdfeca842", - "metadata": { - "scrolled": true - }, - "outputs": [], + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b7c686d503d14bb69250747a881fe3f4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Computing multiple graphs.: 0%| | 0/390 [00:00