{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "6b7abc7b-b435-43d1-9fd8-c349ee8710f3",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Administrar recursos informáticos y de datos de Qiskit Serverless\"\n",
        "description: \"Gestione los recursos informáticos y los datos en todo su patrón Qiskit con Qiskit Serverless.\"\n",
        "---\n",
        "\n",
        "<span id=\"manage-qiskit-serverless-compute-and-data-resources\" />\n",
        "\n",
        "# Administrar recursos informáticos y de datos de Qiskit Serverless\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b0771d6-95c9-46dc-955a-f8702f6a2632",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "<Accordion>\n",
        "  <AccordionItem title=\"Versiones del paquete\">\n",
        "    El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos.\n",
        "    Recomendamos utilizar estas versiones o versiones más recientes.\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á siendo actualizado y sus características están cambiando rápidamente.** Durante esta fase de desarrollo, encontrará las notas de la versión y la documentación más reciente en la página [« Qiskit Serverless » (Notas de la versión y documentación) de GitHub](https://qiskit.github.io/qiskit-serverless/index.html).\n",
        "</Admonition>\n",
        "\n",
        "Con Qiskit Serverless, puedes gestionar la computación y los datos a través de tu [patrón Qiskit](/docs/guides/intro-to-patterns), incluyendo CPUs, QPUs y otros aceleradores de computación.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "380354c0-5cab-464d-b10f-c94055de3605",
      "metadata": {},
      "source": [
        "<span id=\"set-detailed-statuses\" />\n",
        "\n",
        "## Establecer estados detallados\n",
        "\n",
        "Las cargas de trabajo sin servidor tienen varias etapas a lo largo de un flujo de trabajo. Por defecto, los siguientes estados son visibles con `job.status()`:\n",
        "\n",
        "* \\*\\*`QUEUED`\\*\\*la carga de trabajo está en cola para los recursos clásicos\n",
        "* \\*\\*`INITIALIZING`\\*\\*la carga de trabajo\n",
        "* \\*\\*`RUNNING`\\*\\*la carga de trabajo se ejecuta actualmente en recursos clásicos\n",
        "* \\*\\*`DONE`\\*\\*la carga de trabajo se ha completado con éxito\n",
        "\n",
        "También puede establecer estados personalizados que describan con más detalle la etapa específica del flujo de trabajo, como se indica a continuación.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Si estás ejecutando las celdas de código localmente en un cuaderno, verás el [comando ](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-writefile)`%%writefile` mágico. Al ejecutar las celdas con este comando especial, estas se guardan en el disco en lugar de ejecutarse.\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 Qiskit Runtime, 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 Qiskit Runtime 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": [
        "Tras completar con éxito esta carga de trabajo (con `save_result()`), este estado se actualizará a `DONE` automáticamente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b2d40a63-3359-46e9-8f1b-4746b449b407",
      "metadata": {},
      "source": [
        "<span id=\"parallel-workflows\" />\n",
        "\n",
        "## Flujos de trabajo paralelos\n",
        "\n",
        "Para tareas clásicas que se pueden paralelizar, utiliza el `@distribute_task` decorador para definir los requisitos de computación necesarios para ejecutar una tarea. Empieza recordando el `transpile_remote.py` ejemplo del tema «[Escribe tu primer programa en Qiskit Serverless](/docs/guides/serverless-first-program) » con el siguiente código.\n",
        "\n",
        "El siguiente código requiere que ya haya [guardado sus credenciales](/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": [
        "En este ejemplo, ha decorado la función `transpile_remote()` con `@distribute_task(target={\"cpu\": 1})`. Cuando se ejecuta, crea una tarea de trabajador paralela asíncrona con un único núcleo de CPU y devuelve una referencia para realizar un seguimiento del trabajador. Para obtener el resultado, pase la referencia a la función `get()` . Podemos utilizarlo para ejecutar múltiples tareas paralelas:\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",
        "### Explora diferentes configuraciones de tareas\n",
        "\n",
        "Puedes asignar de forma flexible CPU, GPU y memoria a tus tareas a través de `@distribute_task()`. Para Qiskit Serverless en IBM Quantum® Platform, cada programa está equipado con 16 núcleos de CPU y 32 GB de RAM, que se pueden asignar dinámicamente según sea necesario.\n",
        "\n",
        "Los núcleos de CPU pueden asignarse como núcleos de CPU completos, o incluso como asignaciones fraccionadas, como se muestra a continuación.\n",
        "\n",
        "La memoria se asigna en número de bytes. Recordemos que hay 1024 bytes en un kilobyte, 1024 kilobytes en un megabyte y 1024 megabytes en un gigabyte. Para asignar 2 GB de memoria a tu trabajador, necesitas asignar `\"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",
        "## Gestiona los datos de todo tu programa\n",
        "\n",
        "Qiskit Serverless le permite gestionar archivos en el directorio `/data` a través de todos sus programas. Esto incluye varias limitaciones:\n",
        "\n",
        "* Actualmente sólo se admiten los archivos `tar` y `h5`\n",
        "* Esto es sólo un almacenamiento plano `/data` , y no puede tener `/data/folder/` subdirectorios\n",
        "\n",
        "A continuación se muestra cómo cargar archivos. Asegúrate de haber iniciado sesión en Qiskit Serverless con tu cuenta de IBM Quantum (consulta las instrucciones en [Subir a Qiskit Serverless](/docs/guides/serverless-first-program#upload-to-qiskit-serverless) ).\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": [
        "A continuación, puedes listar todos los archivos de tu directorio `data` . Todos los programas pueden acceder a estos datos.\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": [
        "Esto puede hacerse desde un programa utilizando `file_download()` para descargar el archivo al entorno del programa, y descomprimiendo el `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": [
        "En este punto, su programa puede interactuar con los archivos, como lo haría con un experimento local. `file_upload()` `file_download()`, y `file_delete()` pueden ser llamados desde su experimento local, o desde su programa cargado, para una gestión de datos consistente y flexible.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a004dd78-0e0a-4a3b-83cb-333469533ef6",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"info\" title=\"Recomendaciones\">\n",
        "  * Consulte un ejemplo completo que [adapta el código existente a Qiskit Serverless](/docs/guides/serverless-port-code).\n",
        "  * Lea un artículo en el que los investigadores utilizaron Qiskit Serverless y la supercomputación centrada en la cuántica para [explorar la química cuántica](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
}