{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "6b7abc7b-b435-43d1-9fd8-c349ee8710f3",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Gérer les ressources informatiques et de données d' Qiskit Serverless\"\n",
        "description: \"Gérez les calculs et les données dans votre modèle Qiskit à l'aide d' Qiskit Serverless.\"\n",
        "---\n",
        "\n",
        "<span id=\"manage-qiskit-serverless-compute-and-data-resources\" />\n",
        "\n",
        "# Gérer les ressources informatiques et de données d' Qiskit Serverless\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b0771d6-95c9-46dc-955a-f8702f6a2632",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "<Accordion>\n",
        "  <AccordionItem title=\"Versions de package\">\n",
        "    Le code de cette page a été développé en tenant compte des exigences suivantes.\n",
        "    Nous recommandons d'utiliser ces versions ou des versions plus récentes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.0.0\n",
        "    qiskit-ibm-runtime~=0.37.0\n",
        "    qiskit-serverless~=0.22.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "95b2f280-f685-455f-83e9-b172445d7c6a",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\">\n",
        "  **Qiskit Serverless est en cours de mise à niveau et ses fonctionnalités évoluent rapidement.** Pendant cette phase de développement, vous trouverez les notes de mise à jour et la documentation la plus récente sur la page [Qiskit ServerlessGitHub](https://qiskit.github.io/qiskit-serverless/index.html).\n",
        "</Admonition>\n",
        "\n",
        "Avec Qiskit Serverless, vous pouvez gérer le calcul et les données à travers votre [modèle Qiskit](/docs/guides/intro-to-patterns), y compris les CPU, QPU et autres accélérateurs de calcul.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "380354c0-5cab-464d-b10f-c94055de3605",
      "metadata": {},
      "source": [
        "<span id=\"set-detailed-statuses\" />\n",
        "\n",
        "## Définir des statuts détaillés\n",
        "\n",
        "Les charges de travail sans serveur comportent plusieurs étapes dans un flux de travail. Par défaut, les statuts suivants peuvent être consultés à l'adresse `job.status()`:\n",
        "\n",
        "* \\*\\*`QUEUED`\\*\\*la charge de travail est en file d'attente pour les ressources classiques\n",
        "* \\*\\*`INITIALIZING`\\*\\*la charge de travail : la charge de travail est mise en place\n",
        "* **`RUNNING`**: la charge de travail s'exécute actuellement sur des ressources classiques\n",
        "* **`DONE`**: la charge de travail s'est achevée avec succès\n",
        "\n",
        "Vous pouvez également définir des statuts personnalisés qui décrivent plus précisément l'étape spécifique du flux de travail, comme suit.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Si vous exécutez les cellules de code localement dans un notebook, vous verrez apparaître la [commande ](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-writefile)`%%writefile` magique. L'exécution de cellules à l'aide de cette commande spéciale les enregistre sur le disque au lieu de les exécuter.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a69df8bc-5033-45bf-a837-cffa9d29b844",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Writing ./source_files/status_example.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile ./source_files/status_example.py\n",
        "\n",
        "# If you include the preceding `%%writefile` command (visible only when you read this locally in a\n",
        "# notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "from qiskit_serverless import update_status, Job\n",
        "\n",
        "# # If your function has a mapping stage, particularly application functions, you can set the status\n",
        "# to \"RUNNING: MAPPING\" as follows:\n",
        "update_status(Job.MAPPING)\n",
        "\n",
        "# # While handling transpilation, error suppression, and so forth, you can set the status to\n",
        "# \"RUNNING: OPTIMIZING_FOR_HARDWARE\":\n",
        "update_status(Job.OPTIMIZING_HARDWARE)\n",
        "\n",
        "# # After you submit jobs to IBM Quantum Compute Service, the underlying quantum job will be queued. You can set\n",
        "# status to \"RUNNING: WAITING_FOR_QPU\":\n",
        "update_status(Job.WAITING_QPU)\n",
        "\n",
        "# # When the Quantum Compute job starts running on the QPU, set the following status\n",
        "# \"RUNNING: EXECUTING_QPU\":\n",
        "update_status(Job.EXECUTING_QPU)\n",
        "\n",
        "## Once QPU is completed and post-processing has begun, set the status \"RUNNING: POST_PROCESSING\":\n",
        "update_status(Job.POST_PROCESSING)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a8746eae-6f15-4faf-8771-0f3062efc723",
      "metadata": {},
      "source": [
        "Une fois cette charge de travail terminée avec succès (avec `save_result()`), ce statut sera automatiquement mis à jour vers `DONE` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b2d40a63-3359-46e9-8f1b-4746b449b407",
      "metadata": {},
      "source": [
        "<span id=\"parallel-workflows\" />\n",
        "\n",
        "## Flux de travail parallèles\n",
        "\n",
        "Pour les tâches classiques pouvant être parallélisées, utilisez le `@distribute_task` décorateur afin de définir les ressources de calcul nécessaires à l'exécution d'une tâche. Commencez par vous rappeler `transpile_remote.py` l'exemple présenté dans la rubrique «[ Écrivez votre premier programme Qiskit Serverless](/docs/guides/serverless-first-program) » à l'aide du code suivant.\n",
        "\n",
        "Le code suivant suppose que vous ayez déjà [enregistré vos données d'identification](/docs/guides/cloud-setup).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "475d82f0-15cc-4db3-b3b0-54b07822b2a0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Writing ./source_files/transpile_remote.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile ./source_files/transpile_remote.py\n",
        "\n",
        "# If you include the preceding `%%writefile` command (visible only when you read this locally in a\n",
        "# notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_serverless import distribute_task\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "\n",
        "@distribute_task(target={\"cpu\": 1})\n",
        "def transpile_remote(circuit, optimization_level, backend):\n",
        "    \"\"\"\n",
        "    Transpiles an abstract circuit (or list of circuits)\n",
        "    into an ISA circuit for a given backend.\n",
        "    \"\"\"\n",
        "    pass_manager = generate_preset_pass_manager(\n",
        "        optimization_level=optimization_level,\n",
        "        backend=service.backend(backend)\n",
        "    )\n",
        "    isa_circuit = pass_manager.run(circuit)\n",
        "    return isa_circuit"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a5914f1d-f898-4db4-8d1e-ccc8081883b9",
      "metadata": {},
      "source": [
        "Dans cet exemple, vous avez décoré la fonction `transpile_remote()` avec `@distribute_task(target={\"cpu\": 1})`. Lorsqu'il est exécuté, il crée une tâche de travail parallèle asynchrone avec un seul cœur de processeur et renvoie une référence pour suivre le travailleur. Pour récupérer le résultat, passez la référence à la fonction `get()` . Nous pouvons l'utiliser pour exécuter plusieurs tâches en parallèle :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e8fd31e6-9ab9-4d75-9ef9-a2b9ff9ad37a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/transpile_remote.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/transpile_remote.py\n",
        "\n",
        "# If you include the preceding `%%writefile` command\n",
        "# (visible only when you read this locally in a\n",
        "# notebook), running this cell saves to disk rather than\n",
        "# executing the code.\n",
        "\n",
        "from time import time\n",
        "from qiskit_serverless import get, get_arguments, save_result, update_status, Job\n",
        "\n",
        "# Get arguments\n",
        "arguments = get_arguments()\n",
        "circuit = arguments.get(\"circuit\")\n",
        "optimization_level = arguments.get(\"optimization_level\")\n",
        "backend = arguments.get(\"backend\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "74fdcd4a-01cd-46ca-aa24-2a8a3605346f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/transpile_remote.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/transpile_remote.py\n",
        "# If you include the preceding `%%writefile` command\n",
        "# (visible only when you read this locally in a\n",
        "# notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "# Start distributed transpilation\n",
        "update_status(Job.OPTIMIZING_HARDWARE)\n",
        "\n",
        "start_time = time()\n",
        "transpile_worker_references = [\n",
        "    transpile_remote(circuit, optimization_level, backend)\n",
        "    for circuit in arguments.get(\"circuit_list\")\n",
        "]\n",
        "\n",
        "transpiled_circuits = get(transpile_worker_references)\n",
        "end_time = time()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "81696ede-3aa5-4e8c-9d35-fdd70c1bf4db",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/transpile_remote.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/transpile_remote.py\n",
        "# If you include the preceding `%%writefile` command\n",
        "# (visible only when you read this locally in a\n",
        "# notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "# Save result, with metadata\n",
        "result = {\n",
        "    \"circuits\": transpiled_circuits,\n",
        "    \"metadata\": {\n",
        "        \"resource_usage\": {\n",
        "            \"RUNNING: OPTIMIZING_FOR_HARDWARE\": {\n",
        "                \"CPU_TIME\": end_time - start_time,\n",
        "                \"QPU_TIME\": 0,\n",
        "            },\n",
        "        }\n",
        "    },\n",
        "}\n",
        "\n",
        "save_result(result)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "611fe030-4494-46b5-9ea1-9678ac513210",
      "metadata": {},
      "source": [
        "<span id=\"explore-different-task-configurations\" />\n",
        "\n",
        "### Explorez différentes configurations de tâches\n",
        "\n",
        "Vous pouvez allouer de manière flexible le CPU, le GPU et la mémoire à vos tâches via `@distribute_task()`. Pour Qiskit Serverless sur IBM Quantum® Platform, chaque programme est équipé de 16 cœurs de CPU et de 32 Go de RAM, qui peuvent être alloués dynamiquement selon les besoins.\n",
        "\n",
        "Les cœurs de CPU peuvent être alloués en tant que cœurs de CPU complets, ou même en tant qu'allocations fractionnaires, comme indiqué ci-dessous.\n",
        "\n",
        "La mémoire est allouée en nombre d'octets. Rappelons qu'il y a 1024 octets dans un kilo-octet, 1024 kilo-octets dans un méga-octet et 1024 méga-octets dans un giga-octet. Pour allouer 2 Go de mémoire à votre travailleur, vous devez allouer `\"mem\": 2 * 1024 * 1024 * 1024`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "cea90969-cfbf-4181-9ffa-524f3709dc69",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/transpile_remote.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/transpile_remote.py\n",
        "# If you include the preceding `%%writefile` command\n",
        "# (visible only when you read this locally in a\n",
        "# notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "@distribute_task(target={\n",
        "    \"cpu\": 16,\n",
        "    \"mem\": 2 * 1024 * 1024 * 1024\n",
        "})\n",
        "def transpile_remote(circuit, optimization_level, backend):\n",
        "    return None"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6bc45489-56d0-4f46-8659-9df4d1555516",
      "metadata": {},
      "source": [
        "<span id=\"manage-data-across-your-program\" />\n",
        "\n",
        "## Gérez les données dans l'ensemble de votre programme\n",
        "\n",
        "Qiskit Serverless vous permet de gérer les fichiers dans le répertoire `/data` à travers tous vos programmes. Cela implique plusieurs limitations :\n",
        "\n",
        "* Seuls les fichiers `tar` et `h5` sont pris en charge aujourd'hui\n",
        "* Il s'agit uniquement d'un espace de stockage plat `/data` , qui ne peut pas comporter de sous-répertoires `/data/folder/`\n",
        "\n",
        "Voici comment télécharger des fichiers. Assurez-vous d'être authentifié sur Qiskit Serverless avec votre compte IBM Quantum (voir [Télécharger sur Qiskit Serverless](/docs/guides/serverless-first-program#upload-to-qiskit-serverless) pour obtenir des instructions).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "0183278f-8ce3-4466-9255-097b2d211052",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'{\"message\":\"/usr/src/app/media/5e1f442128cdf60018496a04/transpile_demo.tar\"}'"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import tarfile\n",
        "from qiskit_serverless import IBMServerlessClient\n",
        "\n",
        "# Create a tar\n",
        "filename = \"transpile_demo.tar\"\n",
        "file = tarfile.open(filename, \"w\")\n",
        "file.add(\"./source_files/transpile_remote.py\")\n",
        "file.close()\n",
        "\n",
        "# Get a reference to a QiskitFunction\n",
        "serverless = IBMServerlessClient()\n",
        "transpile_remote_demo = next(\n",
        "    program\n",
        "    for program in serverless.list()\n",
        "    if program.title == \"transpile_remote_serverless\"\n",
        ")\n",
        "\n",
        "# Upload the tar to Serverless data directory\n",
        "serverless.file_upload(file=filename, function=transpile_remote_demo)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4f762470-945f-48d5-a65b-c60d3b2dae3f",
      "metadata": {},
      "source": [
        "Vous pouvez ensuite dresser la liste de tous les fichiers contenus dans votre répertoire `data` . Ces données sont accessibles à tous les programmes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "14241fc4-d0cb-4803-8752-a460e1f48708",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['classifier_name.pkl.tar', 'output.json.tar', 'transpile_demo.tar']"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "serverless.files(function=transpile_remote_demo)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a97bd83e-8250-43bb-b1c4-d40d822c7ba2",
      "metadata": {},
      "source": [
        "Cela peut se faire à partir d'un programme en utilisant `file_download()` pour télécharger le fichier dans l'environnement du programme, et en décompressant le fichier `tar`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "ef649b2a-ed95-4dd2-89d9-61438faa7c1e",
      "metadata": {},
      "outputs": [],
      "source": [
        "%%writefile ./source_files/extract_tarfile.py\n",
        "# If you include the preceding `%%writefile` command\n",
        "# (visible only when you read this locally in a\n",
        "# notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "import tarfile\n",
        "from qiskit_serverless import IBMServerlessClient\n",
        "\n",
        "# For `token`, use the 44-character API_KEY you created\n",
        "# and saved from the IBM Quantum Platform Home dashboard\n",
        "serverless = IBMServerlessClient(token=\"<YOUR_API_KEY>\")\n",
        "files = serverless.files()\n",
        "demo_file = files[0]\n",
        "downloaded_tar = serverless.file_download(demo_file)\n",
        "\n",
        "\n",
        "with tarfile.open(downloaded_tar, 'r') as tar:\n",
        "    tar.extractall()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5b93dbdb-2060-468b-8496-ba98142a780b",
      "metadata": {},
      "source": [
        "À ce stade, votre programme peut interagir avec les fichiers, comme vous le feriez avec une expérience locale. `file_upload()` les fichiers de données, `file_download()` et `file_delete()` peuvent être appelés à partir de votre expérience locale ou de votre programme téléchargé, pour une gestion cohérente et flexible des données.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a004dd78-0e0a-4a3b-83cb-333469533ef6",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"info\" title=\"Recommandations\">\n",
        "  * Consultez un exemple complet de [portage de code existant vers l' Qiskit Serverless](/docs/guides/serverless-port-code).\n",
        "  * Lisez un article dans lequel des chercheurs ont utilisé Qiskit Serverless et le supercalculateur centré sur le quantique pour [explorer la chimie quantique](https://arxiv.org/abs/2405.05068v1).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}