{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "6b7abc7b-b435-43d1-9fd8-c349ee8710f3",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Gestisci le risorse di elaborazione e dati dell' Qiskit Serverless\"\n",
        "description: \"Gestisci l'elaborazione e i dati nel tuo modello Qiskit con Qiskit Serverless.\"\n",
        "---\n",
        "\n",
        "<span id=\"manage-qiskit-serverless-compute-and-data-resources\" />\n",
        "\n",
        "# Gestisci le risorse di elaborazione e dati dell' Qiskit Serverless\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b0771d6-95c9-46dc-955a-f8702f6a2632",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "<Accordion>\n",
        "  <AccordionItem title=\"Versioni del pacchetto\">\n",
        "    Il codice di questa pagina è stato sviluppato in base ai seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o versioni più recenti.\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 sta subendo un aggiornamento e le sue caratteristiche stanno cambiando rapidamente.** Durante questa fase di sviluppo, è possibile trovare le note di rilascio e la documentazione più recente alla pagina [Qiskit ServerlessGitHub](https://qiskit.github.io/qiskit-serverless/index.html).\n",
        "</Admonition>\n",
        "\n",
        "Con Qiskit Serverless, è possibile gestire l'elaborazione e i dati attraverso il [modello Qiskit](/docs/guides/intro-to-patterns), comprese le CPU, le QPU e altri acceleratori di calcolo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "380354c0-5cab-464d-b10f-c94055de3605",
      "metadata": {},
      "source": [
        "<span id=\"set-detailed-statuses\" />\n",
        "\n",
        "## Imposta stati dettagliati\n",
        "\n",
        "I carichi di lavoro serverless hanno diverse fasi in un flusso di lavoro. Per impostazione predefinita, i seguenti stati sono visualizzabili con `job.status()`:\n",
        "\n",
        "* **`QUEUED`**: il carico di lavoro è in coda per le risorse classiche\n",
        "* **`INITIALIZING`**: il carico di lavoro è impostato\n",
        "* **`RUNNING`**: il carico di lavoro è attualmente in esecuzione su risorse classiche\n",
        "* **`DONE`**: il carico di lavoro è stato completato con successo\n",
        "\n",
        "È inoltre possibile impostare stati personalizzati che descrivono ulteriormente la fase specifica del flusso di lavoro, come segue.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Se stai leggendo le celle di codice localmente in un notebook, vedrai il [comando ](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-writefile)`%%writefile` magico. L'esecuzione delle celle con questo comando speciale le salva su disco invece di eseguirle.\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": [
        "Dopo aver completato con successo questo carico di lavoro (con `save_result()`), questo stato verrà aggiornato automaticamente a `DONE` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b2d40a63-3359-46e9-8f1b-4746b449b407",
      "metadata": {},
      "source": [
        "<span id=\"parallel-workflows\" />\n",
        "\n",
        "## Flussi di lavoro paralleli\n",
        "\n",
        "Per le attività classiche che possono essere parallelizzate, usa il `@distribute_task` decoratore per definire i requisiti di calcolo necessari per eseguire un'attività. Inizia ricordando `transpile_remote.py` l'esempio dell'argomento \" [Scrivi il tuo primo programma in Qiskit Serverless](/docs/guides/serverless-first-program) \" con il codice seguente.\n",
        "\n",
        "Il codice seguente richiede che tu abbia già [salvato le tue credenziali](/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": [
        "In questo esempio, si è decorata la funzione `transpile_remote()` con `@distribute_task(target={\"cpu\": 1})`. Quando viene eseguito, crea un task worker parallelo asincrono con un singolo core della CPU e restituisce un riferimento per tracciare il worker. Per recuperare il risultato, passare il riferimento alla funzione `get()` . Possiamo usarlo per eseguire più task in parallelo:\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",
        "### Esplora diverse configurazioni delle attività\n",
        "\n",
        "È possibile allocare in modo flessibile la CPU, la GPU e la memoria per i propri compiti tramite `@distribute_task()`. Per Qiskit Serverless su IBM Quantum® Platform, ogni programma è dotato di 16 core di CPU e 32 GB di RAM, che possono essere allocati dinamicamente secondo le necessità.\n",
        "\n",
        "I core della CPU possono essere allocati come core completi o anche in modo frazionario, come mostrato di seguito.\n",
        "\n",
        "La memoria viene allocata in numero di byte. Ricordiamo che ci sono 1024 byte in un kilobyte, 1024 kilobyte in un megabyte e 1024 megabyte in un gigabyte. Per allocare 2 GB di memoria per il worker, è necessario allocare `\"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",
        "## Gestisci i dati in tutto il tuo programma\n",
        "\n",
        "Qiskit Serverless consente di gestire i file nella directory `/data` in tutti i programmi. Ciò comporta diverse limitazioni:\n",
        "\n",
        "* Oggi sono supportati solo i file `tar` e `h5`\n",
        "* Si tratta solo di una memoria piatta `/data` e non può avere sottodirectory `/data/folder/`\n",
        "\n",
        "Di seguito viene illustrato come caricare i file. Assicurati di aver effettuato l'autenticazione su Qiskit Serverless con il tuo account IBM Quantum (vedi [Carica su Qiskit Serverless](/docs/guides/serverless-first-program#upload-to-qiskit-serverless) per le istruzioni).\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": [
        "Successivamente, è possibile elencare tutti i file presenti nella directory `data` . Questi dati sono accessibili a tutti i programmi.\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": [
        "Questo può essere fatto da un programma usando `file_download()` per scaricare il file nell'ambiente del programma e decomprimendo `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": [
        "A questo punto, il programma può interagire con i file come se fosse un esperimento locale. `file_upload()` i file `file_download()` e `file_delete()` possono essere richiamati dall'esperimento locale o dal programma caricato, per una gestione dei dati coerente e flessibile.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a004dd78-0e0a-4a3b-83cb-333469533ef6",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"info\" title=\"Suggerimenti\">\n",
        "  * Guarda un esempio completo che [illustra come trasferire il codice esistente su Qiskit Serverless](/docs/guides/serverless-port-code).\n",
        "  * Leggete un articolo in cui i ricercatori hanno utilizzato Qiskit Serverless e il supercomputing quantum-centrico per [esplorare la chimica quantistica](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
}