From e31e5c8f729f745d3a4db23315710bcb248968d5 Mon Sep 17 00:00:00 2001 From: Carlos Bazaga Date: Mon, 1 Sep 2025 01:31:48 +0200 Subject: [PATCH 1/5] Created C extension generator Notebook. Execution outputs intentionally included to showcase results. (Compiling outputs removed due to sensible information included in logs) --- .../python_c_ext_generator.ipynb | 1616 +++++++++++++++++ 1 file changed, 1616 insertions(+) create mode 100644 week4/community-contributions/c_extension_generator/python_c_ext_generator.ipynb diff --git a/week4/community-contributions/c_extension_generator/python_c_ext_generator.ipynb b/week4/community-contributions/c_extension_generator/python_c_ext_generator.ipynb new file mode 100644 index 0000000..65b480a --- /dev/null +++ b/week4/community-contributions/c_extension_generator/python_c_ext_generator.ipynb @@ -0,0 +1,1616 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4a6ab9a2-28a2-445d-8512-a0dc8d1b54e9", + "metadata": {}, + "source": [ + "# Python C extension generator\n", + "\n", + "Use a Frontier model to generate a high performance Python C extension code from Python code.\n", + "\n", + "Python C extension modules allows to integrate C coded and compiled modules into Python applications.\n", + "\n", + "* [Python C Extensions](https://docs.python.org/3.13/extending/index.html)\n", + "* [Python's C API](https://docs.python.org/3.13/c-api/index.html)" + ] + }, + { + "cell_type": "markdown", + "id": "d90e04a2-5b8a-4fd5-9db8-27c02f033313", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " \n", + " \n", + "

Important Note

\n", + " \n", + " In this lab, I use GPT-4o or GPT-5, which are slightly higher priced models.\n", + " \n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e610bf56-a46e-4aff-8de1-ab49d62b1ad3", + "metadata": {}, + "outputs": [], + "source": [ + "# Imports.\n", + "\n", + "import io\n", + "import os\n", + "import subprocess\n", + "import sys\n", + "from time import perf_counter\n", + "from timeit import timeit\n", + "\n", + "import gradio as gr\n", + "from dotenv import load_dotenv\n", + "from openai import OpenAI\n", + "from pydantic import BaseModel" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4f672e1c-87e9-4865-b760-370fa605e614", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Load environment variables from '.env' file.\n", + "\n", + "load_dotenv(override=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8aa149ed-9298-4d69-8fe2-8f5de0f667da", + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize client and set the default LLM model to use.\n", + "\n", + "# OPENAI_MODEL = \"gpt-4o\"\n", + "OPENAI_MODEL = \"gpt-5\"\n", + "\n", + "openai = OpenAI()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c6f37bf0", + "metadata": {}, + "outputs": [], + "source": [ + "# Define Pydantic model class for GPT response parsing.\n", + "\n", + "class Extension_codes(BaseModel):\n", + " \"\"\"Pydantic model of a response containing the generated C code, the 'setup.py' code and an usage example.\"\"\"\n", + " c_code: str\n", + " setup: str\n", + " usage: str" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cb6ce77a", + "metadata": {}, + "outputs": [], + "source": [ + "# Define a function to print the optimization codes.\n", + "\n", + "def print_optimization(optimization):\n", + " \"\"\"Print the optimization codes.\"\"\"\n", + " print(f\"C CODE:\\n{optimization.c_code}\")\n", + " print(\"---------------------------\")\n", + " print(f\"setup.py:\\n{optimization.setup}\")\n", + " print(\"---------------------------\")\n", + " print(f\"USAGE:\\n{optimization.usage}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "71e1ba8c-5b05-4726-a9f3-8d8c6257350b", + "metadata": {}, + "outputs": [], + "source": [ + "# Define a function to write outputs to a file with a given filename.\n", + "\n", + "def write_file(data, filename):\n", + " \"\"\"Write data to a file with the specified filename.\"\"\"\n", + " with open(filename, \"w\") as file:\n", + " file.write(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "f13c9c97", + "metadata": {}, + "outputs": [], + "source": [ + "# Define a function to write the optimization codes to files.\n", + "\n", + "def write_optimization(optimization, module_name):\n", + " \"\"\"Write the optimization codes to files.\"\"\"\n", + " write_file(optimization.c_code, f\"{module_name}.c\")\n", + " write_file(optimization.setup, \"setup.py\")\n", + " write_file(optimization.usage, \"usage_example.py\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6896636f-923e-4a2c-9d6c-fac07828a201", + "metadata": {}, + "outputs": [], + "source": [ + "# Define system message for the LLM with instructions for generating the C extension code.\n", + "\n", + "system_message = \"\"\"\n", + "You are an assistant that reimplements Python code in high performance C extensions for Python.\n", + "Your responses must always be a JSON with the following structure:\n", + "\n", + "{\n", + " \"c_code\": \"Optimized C extension for Python code\",\n", + " \"setup\": \"The 'setup.py' code to compile the C extension for Python\",\n", + " \"usage\": \"An example of usage of the C extension for Python code with time measurement and comparing with the original Python code\"\n", + "}\n", + "\n", + "Use comments sparingly and do not provide any explanation other than occasional comments.\n", + "The C extension for Python needs to produce an identical output in the fastest possible time.\n", + "Make sure the C extension for Python code is correct and can be compiled with 'python setup.py build' and used in Python.\n", + "The usage example must include a time measurement and a comparison with the original Python code.\n", + "Do not include any additional text or explanation outside the JSON structure.\n", + "Make sure the JSON is correctly formatted.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8e7b3546-57aa-4c29-bc5d-f211970d04eb", + "metadata": {}, + "outputs": [], + "source": [ + "# Define user prompt template and function to fill it.\n", + "\n", + "def user_prompt_for(python_code, module_name):\n", + " user_prompt = f\"\"\"\n", + " Reimplement this Python code as a C extension for Python with the fastest possible implementation that produces identical output in the least time.\n", + " Respond only with C extension for Python code, do not explain your work other than a few code comments.\n", + " The module name, used to import, must be \"{module_name}\", the generated C file will be named \"{module_name}.c\".\n", + " Pay attention to number types to ensure no int overflows.\n", + " Remember to #include all necessary C packages such as iomanip or \n", + "\n", + " The target architecture is {sys.platform}, take that in mind while generating the C code, specially\n", + " when choosing types to use, and use the appropriate compiler flags.\n", + " Make sure to use the Python C API correctly and manage memory properly to avoid leaks or crashes.\n", + "\n", + " Here is the Python code to reimplement:\n", + "\n", + " {python_code}\"\"\"\n", + " return user_prompt" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "c6190659-f54c-4951-bef4-4960f8e51cc4", + "metadata": {}, + "outputs": [], + "source": [ + "# Define function to create the messages for the LLM.\n", + "\n", + "def messages_for(python_code, module_name):\n", + " \"\"\"Create the messages for the LLM given the Python code and the desired module name.\"\"\"\n", + " return [\n", + " {\"role\": \"system\", \"content\": system_message},\n", + " {\"role\": \"user\", \"content\": user_prompt_for(python_code, module_name)}]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "3c57bc55", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SYSTEM: \n", + "You are an assistant that reimplements Python code in high performance C extensions for Python.\n", + "Your responses must always be a JSON with the following structure:\n", + "\n", + "{\n", + " \"c_code\": \"Optimized C extension for Python code\",\n", + " \"setup\": \"The 'setup.py' code to compile the C extension for Python\",\n", + " \"usage\": \"An example of usage of the C extension for Python code with time measurement and comparing with the original Python code\"\n", + "}\n", + "\n", + "Use comments sparingly and do not provide any explanation other than occasional comments.\n", + "The C extension for Python needs to produce an identical output in the fastest possible time.\n", + "Make sure the C extension for Python code is correct and can be compiled with 'python setup.py build' and used in Python.\n", + "The usage example must include a time measurement and a comparison with the original Python code.\n", + "Do not include any additional text or explanation outside the JSON structure.\n", + "Make sure the JSON is correctly formatted.\n", + "\n", + "--------------------------------\n", + "USER: \n", + " Reimplement this Python code as a C extension for Python with the fastest possible implementation that produces identical output in the least time.\n", + " Respond only with C extension for Python code, do not explain your work other than a few code comments.\n", + " The module name, used to import, must be \"say_hello\", the generated C file will be named \"say_hello.c\".\n", + " Pay attention to number types to ensure no int overflows.\n", + " Remember to #include all necessary C packages such as iomanip or \n", + "\n", + " The target architecture is win32, take that in mind while generating the C code, specially\n", + " when choosing types to use, and use the appropriate compiler flags.\n", + " Make sure to use the Python C API correctly and manage memory properly to avoid leaks or crashes.\n", + "\n", + " Here is the Python code to reimplement:\n", + "\n", + " print('Hello World')\n", + "--------------------------------\n" + ] + } + ], + "source": [ + "# Test the messages function and print the messages.\n", + "\n", + "for message in messages_for(\"print('Hello World')\", \"say_hello\"):\n", + " print(f\"{message['role'].upper()}: {message['content']}\")\n", + " print(\"--------------------------------\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "e7d2fea8-74c6-4421-8f1e-0e76d5b201b9", + "metadata": {}, + "outputs": [], + "source": [ + "# Define optimization function using OpenAI's GPT model.\n", + "\n", + "def optimize_gpt(python_code, module_name, model=OPENAI_MODEL):\n", + " \"\"\"Optimize the given Python code by generating a C extension for Python with the specified module name using the specified LLM model.\"\"\"\n", + " response = openai.chat.completions.parse(\n", + " model=model,\n", + " messages=messages_for(python_code, module_name),\n", + " response_format=Extension_codes).choices[0].message.parsed\n", + " return response" + ] + }, + { + "cell_type": "markdown", + "id": "c05b263a", + "metadata": {}, + "source": [ + "# Start with a math function that calculates ***π*** using the Leibniz formula.\n", + "\n", + "This formula implies the iterative approximation of *π* using an alternating series,\n", + "the more iterations the more the precision but with a cost of more computation.\n", + "* [Leibniz formula for π](https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80)\n", + "\n", + "This is a good candidate to get a noticeable improvement by coding and compiling it into a Python C extension. \n", + "\n", + "> NOTE:\n", + ">\n", + "> We are creating an importable module not an executable program so the code to be optimized must contain only declarations such as DEF or CLASS." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "a1cbb778-fa57-43de-b04b-ed523f396c38", + "metadata": {}, + "outputs": [], + "source": [ + "# Define the Python function to be converted to a C extension and its module name.\n", + "\n", + "module_name = \"calculate_pi\"\n", + "\n", + "calculate_pi_code = f\"\"\"\n", + "def leibniz_pi(iterations):\n", + " result = 1.0\n", + " for i in range(1, iterations+1):\n", + " j = i * 4 - 1\n", + " result -= (1/j)\n", + " j = i * 4 + 1\n", + " result += (1/j)\n", + " return result * 4\n", + "\"\"\"\n", + "\n", + "# Define a function to test the performance of the calculus function.\n", + "\n", + "def test_pi_calculation(calculus_function ,iterations=100_000_000):\n", + " \"\"\"Test the performance of the given calculus function.\"\"\"\n", + " start_time = perf_counter()\n", + " result = calculus_function(iterations)\n", + " end_time = perf_counter()\n", + " print(f\"Result: {result:.12f}\")\n", + " print(f\"Execution Time: {(end_time - start_time):.6f} seconds\")\n", + "\n", + "# Execute function declaration.\n", + "exec(calculate_pi_code)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "7fe1cd4b-d2c5-4303-afed-2115a3fef200", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result: 3.141592658589\n", + "Execution Time: 20.556854 seconds\n" + ] + } + ], + "source": [ + "# Run original python code and time it.\n", + "\n", + "test_pi_calculation(leibniz_pi, 100_000_000)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "4c0be0f2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Timing...\n", + "Python average execution time: 21.158541 seconds\n" + ] + } + ], + "source": [ + "# Average timing the original Python code running it several times.\n", + "# (Increase 'iterations' for better timing)\n", + "\n", + "print(\"Timing...\")\n", + "iterations = 5\n", + "average = timeit(lambda: leibniz_pi(100_000_000), number=iterations) / iterations\n", + "print(f\"Python average execution time: {average:.6f} seconds\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "105db6f9-343c-491d-8e44-3a5328b81719", + "metadata": {}, + "outputs": [], + "source": [ + "# Request code optimization using GPT.\n", + "\n", + "optimization = optimize_gpt(calculate_pi_code, module_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "378981c7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C CODE:\n", + "#define PY_SSIZE_T_CLEAN\n", + "#include \n", + "#include \n", + "#include \n", + "#include \n", + "#include \n", + "\n", + "static PyObject* leibniz_pi(PyObject* self, PyObject* args) {\n", + " PyObject* iterations_obj;\n", + " if (!PyArg_ParseTuple(args, \"O\", &iterations_obj)) {\n", + " return NULL;\n", + " }\n", + "\n", + " long long n_signed;\n", + " int overflow = 0;\n", + " n_signed = PyLong_AsLongLongAndOverflow(iterations_obj, &overflow);\n", + " if (n_signed == -1 && PyErr_Occurred() && overflow == 0) {\n", + " return NULL;\n", + " }\n", + "\n", + " unsigned long long n = 0ULL;\n", + " if (overflow < 0) {\n", + " n = 0ULL;\n", + " } else if (overflow > 0) {\n", + " unsigned long long tmp = PyLong_AsUnsignedLongLong(iterations_obj);\n", + " if (tmp == (unsigned long long)-1 && PyErr_Occurred()) {\n", + " return NULL;\n", + " }\n", + " n = tmp;\n", + " } else {\n", + " if (n_signed <= 0) {\n", + " n = 0ULL;\n", + " } else {\n", + " n = (unsigned long long)n_signed;\n", + " }\n", + " }\n", + "\n", + " double result = 1.0;\n", + " if (n == 0ULL) {\n", + " return PyFloat_FromDouble(result * 4.0);\n", + " }\n", + "\n", + " Py_BEGIN_ALLOW_THREADS\n", + " for (unsigned long long i = 1ULL; i <= n; ++i) {\n", + " double jd1;\n", + " if (i <= ULLONG_MAX / 4ULL) {\n", + " unsigned long long j1 = i * 4ULL - 1ULL;\n", + " jd1 = (double)j1;\n", + " } else {\n", + " jd1 = (double)i * 4.0 - 1.0;\n", + " }\n", + " result -= 1.0 / jd1;\n", + "\n", + " double jd2;\n", + " if (i <= (ULLONG_MAX - 1ULL) / 4ULL) {\n", + " unsigned long long j2 = i * 4ULL + 1ULL;\n", + " jd2 = (double)j2;\n", + " } else {\n", + " jd2 = (double)i * 4.0 + 1.0;\n", + " }\n", + " result += 1.0 / jd2;\n", + " }\n", + " Py_END_ALLOW_THREADS\n", + "\n", + " return PyFloat_FromDouble(result * 4.0);\n", + "}\n", + "\n", + "static PyMethodDef CalculatePiMethods[] = {\n", + " {\"leibniz_pi\", leibniz_pi, METH_VARARGS, \"Compute pi using the Leibniz series with the given number of iterations.\"},\n", + " {NULL, NULL, 0, NULL}\n", + "};\n", + "\n", + "static struct PyModuleDef calculate_pimodule = {\n", + " PyModuleDef_HEAD_INIT,\n", + " \"calculate_pi\",\n", + " \"High-performance Leibniz pi calculation.\",\n", + " -1,\n", + " CalculatePiMethods\n", + "};\n", + "\n", + "PyMODINIT_FUNC PyInit_calculate_pi(void) {\n", + " return PyModule_Create(&calculate_pimodule);\n", + "}\n", + "\n", + "---------------------------\n", + "setup.py:\n", + "from setuptools import setup, Extension\n", + "import sys\n", + "import os\n", + "\n", + "extra_compile_args = []\n", + "extra_link_args = []\n", + "\n", + "if os.name == 'nt':\n", + " extra_compile_args.extend(['/O2', '/fp:precise'])\n", + "else:\n", + " extra_compile_args.extend(['-O3', '-fno-strict-aliasing'])\n", + "\n", + "module = Extension(\n", + " 'calculate_pi',\n", + " sources=['calculate_pi.c'],\n", + " extra_compile_args=extra_compile_args,\n", + " extra_link_args=extra_link_args,\n", + ")\n", + "\n", + "setup(\n", + " name='calculate_pi',\n", + " version='1.0.0',\n", + " description='High-performance C extension for computing pi via the Leibniz series',\n", + " ext_modules=[module],\n", + ")\n", + "\n", + "---------------------------\n", + "USAGE:\n", + "# Build first: python setup.py build_ext --inplace\n", + "import time\n", + "import math\n", + "import calculate_pi\n", + "\n", + "# Original Python implementation\n", + "def py_leibniz_pi(iterations):\n", + " result = 1.0\n", + " for i in range(1, iterations + 1):\n", + " j = i * 4 - 1\n", + " result -= (1 / j)\n", + " j = i * 4 + 1\n", + " result += (1 / j)\n", + " return result * 4\n", + "\n", + "iters = 5_000_000\n", + "\n", + "# Warm-up\n", + "calculate_pi.leibniz_pi(10)\n", + "py_leibniz_pi(10)\n", + "\n", + "start = time.perf_counter()\n", + "res_c = calculate_pi.leibniz_pi(iters)\n", + "end = time.perf_counter()\n", + "ctime = end - start\n", + "\n", + "start = time.perf_counter()\n", + "res_py = py_leibniz_pi(iters)\n", + "end = time.perf_counter()\n", + "pytime = end - start\n", + "\n", + "print(f\"Iterations: {iters}\")\n", + "print(f\"C extension result: {res_c}\")\n", + "print(f\"Python result: {res_py}\")\n", + "print(f\"Absolute difference: {abs(res_c - res_py)}\")\n", + "print(f\"C extension time: {ctime:.6f} s\")\n", + "print(f\"Python time: {pytime:.6f} s\")\n", + "print(f\"Speedup: {pytime/ctime if ctime > 0 else float('inf'):.2f}x\")\n", + "\n" + ] + } + ], + "source": [ + "# Print generated extension code.\n", + "\n", + "print_optimization(optimization)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "ae9a4a64", + "metadata": {}, + "outputs": [], + "source": [ + "# Write the generated code to files.\n", + "# (Will overwrite existing files)\n", + "\n", + "write_optimization(optimization, module_name)" + ] + }, + { + "cell_type": "markdown", + "id": "bf8f8018-f64d-425c-a0e1-d7862aa9592d", + "metadata": {}, + "source": [ + "# Compiling C Extension and executing\n", + "\n", + "The python setup command may fail inside Jupyter lab, if that's the case try it directly on the command line.\n", + "\n", + "There are two cells with WINDOWS ONLY, those are to manage the fact windows comes with two command lines,\n", + "the old CMD (MS-DOS style) and the new POWERSHELL (Unix style).\n", + "\n", + "It is controlled by the COMSPEC environment variable.\\\n", + "*(Using this variable is completely innocuous on UNIX systems, they will simply ignore it)*\n", + "\n", + "Most of command lines present here are Unix style but the building one requires CMD so\n", + "we switch to CMD before compiling to later restore the preset one." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "22a9130e", + "metadata": {}, + "outputs": [], + "source": [ + "# Clean previous builds.\n", + "# (Make sure to run this cell before running the compile cell a second time only)\n", + "# (May cast errors if no previous build exists)\n", + "\n", + "!rm -r build/" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "816e7c9d", + "metadata": {}, + "outputs": [], + "source": [ + "# [WINDOWS ONLY]\n", + "# Set COMSPEC to cmd.exe to avoid issues with some C compilers on Windows.\n", + "# (Remember to restore original COMSPEC after compilation and testing)\n", + "preset_comspec = os.environ.get(\"COMSPEC\")\n", + "os.environ[\"COMSPEC\"] = \"C:\\\\Windows\\\\System32\\\\cmd.exe\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4194e40c-04ab-4940-9d64-b4ad37c5bb40", + "metadata": {}, + "outputs": [], + "source": [ + "# Compile the C extension.\n", + "# (Will fail no C compiler is installed)\n", + "# (In case of errors, try directly on the command line)\n", + "\n", + "!python setup.py build_ext --inplace" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "8db12c4d", + "metadata": {}, + "outputs": [], + "source": [ + "# [WINDOWS ONLY]\n", + "# Restore original COMSPEC.\n", + "\n", + "os.environ[\"COMSPEC\"] = preset_comspec" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "a8f5169f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iterations: 5000000\n", + "C extension result: 3.1415927535897814\n", + "Python result: 3.1415927535897814\n", + "Absolute difference: 0.0\n", + "C extension time: 0.037515 s\n", + "Python time: 1.046732 s\n", + "Speedup: 27.90x\n" + ] + } + ], + "source": [ + "# Run the usage example to test the compiled C extension.\n", + "exec(optimization.usage)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "a1972472", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Testing original Python code:\n", + "Result: 3.141592658589\n", + "Execution Time: 20.350486 seconds\n", + "Testing C extension code:\n", + "Result: 3.141592658589\n", + "Execution Time: 0.759571 seconds\n" + ] + } + ], + "source": [ + "# Import newly created C extension and compare performance with original Python code.\n", + "\n", + "from calculate_pi import leibniz_pi as c_leibniz_pi\n", + "\n", + "print(\"Testing original Python code:\")\n", + "test_pi_calculation(leibniz_pi, 100_000_000)\n", + "print(\"Testing C extension code:\")\n", + "test_pi_calculation(c_leibniz_pi, 100_000_000)\n" + ] + }, + { + "cell_type": "markdown", + "id": "77304493", + "metadata": {}, + "source": [ + "# Lets try with a more complex code\n", + "\n", + "Now we define three functions that together implements the calculation of the \"total maximum subarray sum\"\n", + "by finding the largest sum of a contiguous subarray within a given array of numbers.\n", + "\n", + "* [Maximum subarray problem](https://en.wikipedia.org/wiki/Maximum_subarray_problem)\n", + "\n", + "This algorithm requires much more computation and steps than the previous one, we may expect a heavy\n", + "improvement by coding and compiling it into a Python C extension. \n", + "\n", + "> NOTE:\n", + ">\n", + "> We are creating an importable module not an executable program so the code to be optimized must contain only declarations such as DEF or CLASS." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "c3b497b3-f569-420e-b92e-fb0f49957ce0", + "metadata": {}, + "outputs": [], + "source": [ + "# Define the Python function to be converted to a C extension and its module name.\n", + "\n", + "module_name = \"python_hard\"\n", + "\n", + "python_hard_code = \"\"\"\n", + "# Be careful to support large number sizes\n", + "\n", + "def lcg(seed, a=1664525, c=1013904223, m=2**32):\n", + " value = seed\n", + " while True:\n", + " value = (a * value + c) % m\n", + " yield value\n", + "\n", + "def max_subarray_sum(n, seed, min_val, max_val):\n", + " lcg_gen = lcg(seed)\n", + " random_numbers = [next(lcg_gen) % (max_val - min_val + 1) + min_val for _ in range(n)]\n", + " max_sum = float('-inf')\n", + " for i in range(n):\n", + " current_sum = 0\n", + " for j in range(i, n):\n", + " current_sum += random_numbers[j]\n", + " if current_sum > max_sum:\n", + " max_sum = current_sum\n", + " return max_sum\n", + "\n", + "def total_max_subarray_sum(n, initial_seed, min_val, max_val):\n", + " total_sum = 0\n", + " lcg_gen = lcg(initial_seed)\n", + " for _ in range(20):\n", + " seed = next(lcg_gen)\n", + " total_sum += max_subarray_sum(n, seed, min_val, max_val)\n", + " return total_sum\n", + "\"\"\"\n", + "\n", + "# Define a function to test the performance of the calculus function.\n", + "\n", + "def test_subarray_sum(calculus_function ,n=1000, initial_seed=42, min_val=-10, max_val=10):\n", + " \"\"\"Test the performance of the given calculus function.\"\"\"\n", + " start_time = perf_counter()\n", + " result = calculus_function(n, initial_seed, min_val, max_val)\n", + " end_time = perf_counter()\n", + " print(\"Total Maximum Subarray Sum (20 runs):\", result)\n", + " print(\"Execution Time: {:.6f} seconds\".format(end_time - start_time))\n", + "\n", + "\n", + "# Execute function declarations.\n", + "exec(python_hard_code)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dab5e4bc-276c-4555-bd4c-12c699d5e899", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total Maximum Subarray Sum (20 runs): 10980\n", + "Execution Time: 61.362418 seconds\n" + ] + } + ], + "source": [ + "# Run original python code and time it.\n", + "\n", + "test_subarray_sum(total_max_subarray_sum, 10000, 42, -10, 10)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "e8d24ed5-2c15-4f55-80e7-13a3952b3cb8", + "metadata": {}, + "outputs": [], + "source": [ + "# Request code optimization using GPT.\n", + "\n", + "optimization = optimize_gpt(python_hard_code, module_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "b888d5af", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C CODE:\n", + "#include \n", + "#include \n", + "#include \n", + "#include \n", + "#include \n", + "\n", + "// LCG step with 32-bit wrap-around\n", + "static inline uint32_t lcg_next(uint32_t *state) {\n", + " *state = (uint32_t)(1664525u * (*state) + 1013904223u);\n", + " return *state;\n", + "}\n", + "\n", + "static inline int add_overflow_int64(int64_t a, int64_t b, int64_t *res) {\n", + " if ((b > 0 && a > INT64_MAX - b) || (b < 0 && a < INT64_MIN - b)) return 1;\n", + " *res = a + b;\n", + " return 0;\n", + "}\n", + "\n", + "// Kadane for int64 array with overflow detection; returns PyLong or NULL (on overflow -> signal via *overflowed)\n", + "static PyObject* kadane_int64(const int64_t *arr, Py_ssize_t n, int *overflowed) {\n", + " if (n <= 0) {\n", + " return PyFloat_FromDouble(-INFINITY);\n", + " }\n", + " int64_t meh = arr[0];\n", + " int64_t msf = arr[0];\n", + " for (Py_ssize_t i = 1; i < n; ++i) {\n", + " int64_t x = arr[i];\n", + " if (meh > 0) {\n", + " int64_t tmp;\n", + " if (add_overflow_int64(meh, x, &tmp)) { *overflowed = 1; return NULL; }\n", + " meh = tmp;\n", + " } else {\n", + " meh = x;\n", + " }\n", + " if (meh > msf) msf = meh;\n", + " }\n", + " return PyLong_FromLongLong(msf);\n", + "}\n", + "\n", + "// Kadane for PyObject* integer array\n", + "static PyObject* kadane_big(PyObject **arr, Py_ssize_t n) {\n", + " if (n <= 0) {\n", + " return PyFloat_FromDouble(-INFINITY);\n", + " }\n", + " PyObject *meh = arr[0]; Py_INCREF(meh);\n", + " PyObject *msf = arr[0]; Py_INCREF(msf);\n", + " PyObject *zero = PyLong_FromLong(0);\n", + " if (!zero) { Py_DECREF(meh); Py_DECREF(msf); return NULL; }\n", + "\n", + " for (Py_ssize_t i = 1; i < n; ++i) {\n", + " int cmp = PyObject_RichCompareBool(meh, zero, Py_GT);\n", + " if (cmp < 0) { Py_DECREF(meh); Py_DECREF(msf); Py_DECREF(zero); return NULL; }\n", + " if (cmp == 1) {\n", + " PyObject *t = PyNumber_Add(meh, arr[i]);\n", + " if (!t) { Py_DECREF(meh); Py_DECREF(msf); Py_DECREF(zero); return NULL; }\n", + " Py_DECREF(meh);\n", + " meh = t;\n", + " } else {\n", + " Py_DECREF(meh);\n", + " meh = arr[i]; Py_INCREF(meh);\n", + " }\n", + " int cmp2 = PyObject_RichCompareBool(meh, msf, Py_GT);\n", + " if (cmp2 < 0) { Py_DECREF(meh); Py_DECREF(msf); Py_DECREF(zero); return NULL; }\n", + " if (cmp2 == 1) {\n", + " Py_DECREF(msf);\n", + " msf = meh; Py_INCREF(msf);\n", + " }\n", + " }\n", + " Py_DECREF(meh);\n", + " Py_DECREF(zero);\n", + " return msf; // new reference\n", + "}\n", + "\n", + "// Generate int64 array fast path; returns 0 on success\n", + "static int gen_array_int64(Py_ssize_t n, uint32_t seed, int64_t min_v, int64_t max_v, int64_t *out) {\n", + " uint32_t state = seed;\n", + " uint64_t umax = (uint64_t)max_v;\n", + " uint64_t umin = (uint64_t)min_v;\n", + " uint64_t range = (umax - umin) + 1ULL; // max>=min guaranteed by caller\n", + " for (Py_ssize_t i = 0; i < n; ++i) {\n", + " state = lcg_next(&state);\n", + " uint32_t r32 = state;\n", + " uint64_t r = (range > 0x100000000ULL) ? (uint64_t)r32 : ((uint64_t)r32 % range);\n", + " int64_t val = (int64_t)(min_v + (int64_t)r);\n", + " out[i] = val;\n", + " }\n", + " return 0;\n", + "}\n", + "\n", + "// Generate PyObject* int array general path using Python arithmetic\n", + "static PyObject** gen_array_big(Py_ssize_t n, uint32_t seed, PyObject *min_val, PyObject *max_val) {\n", + " PyObject **arr = (PyObject**)PyMem_Malloc((n > 0 ? n : 1) * sizeof(PyObject*));\n", + " if (!arr) {\n", + " PyErr_NoMemory();\n", + " return NULL;\n", + " }\n", + " PyObject *one = PyLong_FromLong(1);\n", + " if (!one) { PyMem_Free(arr); return NULL; }\n", + " PyObject *diff = PyNumber_Subtract(max_val, min_val);\n", + " if (!diff) { Py_DECREF(one); PyMem_Free(arr); return NULL; }\n", + " PyObject *range_obj = PyNumber_Add(diff, one);\n", + " Py_DECREF(diff);\n", + " Py_DECREF(one);\n", + " if (!range_obj) { PyMem_Free(arr); return NULL; }\n", + "\n", + " uint32_t state = seed;\n", + " for (Py_ssize_t i = 0; i < n; ++i) {\n", + " state = lcg_next(&state);\n", + " PyObject *v = PyLong_FromUnsignedLong((unsigned long)state);\n", + " if (!v) {\n", + " Py_DECREF(range_obj);\n", + " for (Py_ssize_t k = 0; k < i; ++k) Py_DECREF(arr[k]);\n", + " PyMem_Free(arr);\n", + " return NULL;\n", + " }\n", + " PyObject *r = PyNumber_Remainder(v, range_obj);\n", + " Py_DECREF(v);\n", + " if (!r) {\n", + " Py_DECREF(range_obj);\n", + " for (Py_ssize_t k = 0; k < i; ++k) Py_DECREF(arr[k]);\n", + " PyMem_Free(arr);\n", + " return NULL;\n", + " }\n", + " PyObject *val = PyNumber_Add(r, min_val);\n", + " Py_DECREF(r);\n", + " if (!val) {\n", + " Py_DECREF(range_obj);\n", + " for (Py_ssize_t k = 0; k < i; ++k) Py_DECREF(arr[k]);\n", + " PyMem_Free(arr);\n", + " return NULL;\n", + " }\n", + " arr[i] = val;\n", + " }\n", + " Py_DECREF(range_obj);\n", + " return arr;\n", + "}\n", + "\n", + "static PyObject* max_subarray_sum_internal(Py_ssize_t n, uint32_t seed, PyObject *min_val, PyObject *max_val) {\n", + " if (n <= 0) {\n", + " return PyFloat_FromDouble(-INFINITY);\n", + " }\n", + "\n", + " if (PyLong_Check(min_val) && PyLong_Check(max_val)) {\n", + " int overflow1 = 0, overflow2 = 0;\n", + " long long min64 = PyLong_AsLongLongAndOverflow(min_val, &overflow1);\n", + " if (overflow1) goto BIGINT_PATH;\n", + " long long max64 = PyLong_AsLongLongAndOverflow(max_val, &overflow2);\n", + " if (overflow2) goto BIGINT_PATH;\n", + " if (max64 >= min64) {\n", + " int64_t *arr = (int64_t*)PyMem_Malloc((size_t)n * sizeof(int64_t));\n", + " if (!arr) { PyErr_NoMemory(); return NULL; }\n", + " if (gen_array_int64(n, seed, (int64_t)min64, (int64_t)max64, arr) != 0) {\n", + " PyMem_Free(arr);\n", + " return NULL;\n", + " }\n", + " int overflowed = 0;\n", + " PyObject *res = kadane_int64(arr, n, &overflowed);\n", + " if (!res && overflowed) {\n", + " // fallback to big-int Kadane\n", + " PyObject **arr_obj = (PyObject**)PyMem_Malloc((size_t)n * sizeof(PyObject*));\n", + " if (!arr_obj) { PyMem_Free(arr); PyErr_NoMemory(); return NULL; }\n", + " for (Py_ssize_t i = 0; i < n; ++i) {\n", + " arr_obj[i] = PyLong_FromLongLong(arr[i]);\n", + " if (!arr_obj[i]) {\n", + " for (Py_ssize_t k = 0; k < i; ++k) Py_DECREF(arr_obj[k]);\n", + " PyMem_Free(arr_obj);\n", + " PyMem_Free(arr);\n", + " return NULL;\n", + " }\n", + " }\n", + " PyObject *bires = kadane_big(arr_obj, n);\n", + " for (Py_ssize_t i = 0; i < n; ++i) Py_DECREF(arr_obj[i]);\n", + " PyMem_Free(arr_obj);\n", + " PyMem_Free(arr);\n", + " return bires;\n", + " }\n", + " PyMem_Free(arr);\n", + " return res;\n", + " }\n", + " }\n", + "BIGINT_PATH: ;\n", + " PyObject **arr_obj = gen_array_big(n, seed, min_val, max_val);\n", + " if (!arr_obj) return NULL;\n", + " PyObject *res = kadane_big(arr_obj, n);\n", + " for (Py_ssize_t i = 0; i < n; ++i) Py_DECREF(arr_obj[i]);\n", + " PyMem_Free(arr_obj);\n", + " return res;\n", + "}\n", + "\n", + "static PyObject* py_max_subarray_sum(PyObject *self, PyObject *args) {\n", + " Py_ssize_t n;\n", + " PyObject *seed_obj, *min_val, *max_val;\n", + " if (!PyArg_ParseTuple(args, \"nOOO\", &n, &seed_obj, &min_val, &max_val)) return NULL;\n", + " if (n < 0) n = 0;\n", + " uint32_t seed = (uint32_t)(PyLong_AsUnsignedLongLongMask(seed_obj) & 0xFFFFFFFFULL);\n", + " if (PyErr_Occurred()) return NULL;\n", + " return max_subarray_sum_internal(n, seed, min_val, max_val);\n", + "}\n", + "\n", + "static PyObject* py_total_max_subarray_sum(PyObject *self, PyObject *args) {\n", + " Py_ssize_t n;\n", + " PyObject *init_seed_obj, *min_val, *max_val;\n", + " if (!PyArg_ParseTuple(args, \"nOOO\", &n, &init_seed_obj, &min_val, &max_val)) return NULL;\n", + " if (n < 0) n = 0;\n", + " uint32_t state = (uint32_t)(PyLong_AsUnsignedLongLongMask(init_seed_obj) & 0xFFFFFFFFULL);\n", + " if (PyErr_Occurred()) return NULL;\n", + "\n", + " PyObject *total = PyLong_FromLong(0);\n", + " if (!total) return NULL;\n", + "\n", + " for (int i = 0; i < 20; ++i) {\n", + " uint32_t seed = lcg_next(&state);\n", + " PyObject *part = max_subarray_sum_internal(n, seed, min_val, max_val);\n", + " if (!part) { Py_DECREF(total); return NULL; }\n", + " PyObject *new_total = PyNumber_Add(total, part);\n", + " Py_DECREF(part);\n", + " if (!new_total) { Py_DECREF(total); return NULL; }\n", + " Py_DECREF(total);\n", + " total = new_total;\n", + " }\n", + " return total;\n", + "}\n", + "\n", + "static PyMethodDef module_methods[] = {\n", + " {\"max_subarray_sum\", (PyCFunction)py_max_subarray_sum, METH_VARARGS, \"Compute maximum subarray sum using LCG-generated array.\"},\n", + " {\"total_max_subarray_sum\", (PyCFunction)py_total_max_subarray_sum, METH_VARARGS, \"Compute total of maximum subarray sums over 20 LCG seeds.\"},\n", + " {NULL, NULL, 0, NULL}\n", + "};\n", + "\n", + "static struct PyModuleDef moduledef = {\n", + " PyModuleDef_HEAD_INIT,\n", + " \"python_hard\",\n", + " NULL,\n", + " -1,\n", + " module_methods,\n", + " NULL,\n", + " NULL,\n", + " NULL,\n", + " NULL\n", + "};\n", + "\n", + "PyMODINIT_FUNC PyInit_python_hard(void) {\n", + " return PyModule_Create(&moduledef);\n", + "}\n", + "\n", + "---------------------------\n", + "setup.py:\n", + "from setuptools import setup, Extension\n", + "import sys\n", + "\n", + "extra_compile_args = []\n", + "extra_link_args = []\n", + "if sys.platform == 'win32':\n", + " extra_compile_args = ['/O2', '/Ot', '/GL', '/fp:fast']\n", + " extra_link_args = ['/LTCG']\n", + "else:\n", + " extra_compile_args = ['-O3', '-march=native']\n", + "\n", + "module = Extension(\n", + " name='python_hard',\n", + " sources=['python_hard.c'],\n", + " extra_compile_args=extra_compile_args,\n", + " extra_link_args=extra_link_args,\n", + " language='c'\n", + ")\n", + "\n", + "setup(\n", + " name='python_hard',\n", + " version='1.0.0',\n", + " description='High-performance C extension reimplementation',\n", + " ext_modules=[module]\n", + ")\n", + "\n", + "---------------------------\n", + "USAGE:\n", + "import time\n", + "\n", + "# Original Python code\n", + "\n", + "def lcg(seed, a=1664525, c=1013904223, m=2**32):\n", + " value = seed\n", + " while True:\n", + " value = (a * value + c) % m\n", + " yield value\n", + "\n", + "def max_subarray_sum_py(n, seed, min_val, max_val):\n", + " lcg_gen = lcg(seed)\n", + " random_numbers = [next(lcg_gen) % (max_val - min_val + 1) + min_val for _ in range(n)]\n", + " max_sum = float('-inf')\n", + " for i in range(n):\n", + " current_sum = 0\n", + " for j in range(i, n):\n", + " current_sum += random_numbers[j]\n", + " if current_sum > max_sum:\n", + " max_sum = current_sum\n", + " return max_sum\n", + "\n", + "def total_max_subarray_sum_py(n, initial_seed, min_val, max_val):\n", + " total_sum = 0\n", + " lcg_gen = lcg(initial_seed)\n", + " for _ in range(20):\n", + " seed = next(lcg_gen)\n", + " total_sum += max_subarray_sum_py(n, seed, min_val, max_val)\n", + " return total_sum\n", + "\n", + "# Build and import extension (after running: python setup.py build && install or develop)\n", + "import python_hard as ext\n", + "\n", + "# Example parameters\n", + "n = 600\n", + "initial_seed = 12345678901234567890\n", + "min_val = -1000\n", + "max_val = 1000\n", + "\n", + "# Time Python\n", + "t0 = time.perf_counter()\n", + "py_res1 = max_subarray_sum_py(n, (initial_seed * 1664525 + 1013904223) % (2**32), min_val, max_val)\n", + "t1 = time.perf_counter()\n", + "py_time1 = t1 - t0\n", + "\n", + "# Time C extension\n", + "t0 = time.perf_counter()\n", + "ext_res1 = ext.max_subarray_sum(n, (initial_seed * 1664525 + 1013904223) % (2**32), min_val, max_val)\n", + "t1 = time.perf_counter()\n", + "ext_time1 = t1 - t0\n", + "\n", + "print('max_subarray_sum equality:', py_res1 == ext_res1)\n", + "print('Python time:', py_time1)\n", + "print('C ext time:', ext_time1)\n", + "\n", + "# Total over 20 seeds\n", + "t0 = time.perf_counter()\n", + "py_res2 = total_max_subarray_sum_py(n, initial_seed, min_val, max_val)\n", + "t1 = time.perf_counter()\n", + "py_time2 = t1 - t0\n", + "\n", + "t0 = time.perf_counter()\n", + "ext_res2 = ext.total_max_subarray_sum(n, initial_seed, min_val, max_val)\n", + "t1 = time.perf_counter()\n", + "ext_time2 = t1 - t0\n", + "\n", + "print('total_max_subarray_sum equality:', py_res2 == ext_res2)\n", + "print('Python total time:', py_time2)\n", + "print('C ext total time:', ext_time2)\n", + "\n" + ] + } + ], + "source": [ + "# Print generated extension code.\n", + "\n", + "print_optimization(optimization)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "356969b8", + "metadata": {}, + "outputs": [], + "source": [ + "# Write the generated extension code to files.\n", + "# (Will overwrite existing files)\n", + "\n", + "write_optimization(optimization, module_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "e0b3d073-88a2-40b2-831c-6f0c345c256f", + "metadata": {}, + "outputs": [], + "source": [ + "# Clean previous builds.\n", + "# (Make sure to run this cell before running the compile cell a second time only)\n", + "# (May cast errors if no previous build exists)\n", + "\n", + "!rm -r build/" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "29ae1993", + "metadata": {}, + "outputs": [], + "source": [ + "# [WINDOWS ONLY]\n", + "# Set COMSPEC to cmd.exe to avoid issues with some C compilers on Windows.\n", + "# (Remember to restore original COMSPEC after compilation and testing)\n", + "preset_comspec = os.environ.get(\"COMSPEC\")\n", + "os.environ[\"COMSPEC\"] = \"C:\\\\Windows\\\\System32\\\\cmd.exe\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "772328a7", + "metadata": {}, + "outputs": [], + "source": [ + "# Compile the C extension.\n", + "# (Will fail no C compiler is installed)\n", + "# (In case of errors, try directly on the command line)\n", + "\n", + "!python setup.py build_ext --inplace" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "4186a19e", + "metadata": {}, + "outputs": [], + "source": [ + "# [WINDOWS ONLY]\n", + "# Restore original COMSPEC.\n", + "\n", + "os.environ[\"COMSPEC\"] = preset_comspec" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "64899bb1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "max_subarray_sum equality: True\n", + "Python time: 0.010335999992094003\n", + "C ext time: 1.4399993233382702e-05\n", + "total_max_subarray_sum equality: True\n", + "Python total time: 0.21065390000876505\n", + "C ext total time: 0.00012310000602155924\n" + ] + } + ], + "source": [ + "# Run the usage example to test the compiled C extension.\n", + "exec(optimization.usage)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "ee4f8f62", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Testing original Python code:\n", + "Total Maximum Subarray Sum (20 runs): 10980\n", + "Execution Time: 57.275276 seconds\n", + "Testing C extension code:\n", + "Total Maximum Subarray Sum (20 runs): 10980\n", + "Execution Time: 0.002317 seconds\n" + ] + } + ], + "source": [ + "# Import newly created C extension and compare performance with original Python code.\n", + "\n", + "from python_hard import total_max_subarray_sum as c_total_max_subarray_sum\n", + "\n", + "print(\"Testing original Python code:\")\n", + "test_subarray_sum(total_max_subarray_sum, 10000, 42, -10, 10)\n", + "print(\"Testing C extension code:\")\n", + "test_subarray_sum(c_total_max_subarray_sum, 10000, 42, -10, 10)" + ] + }, + { + "cell_type": "markdown", + "id": "85945330", + "metadata": {}, + "source": [ + "# Let's build a Gradio service" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "2f1ae8f5-16c8-40a0-aa18-63b617df078d", + "metadata": {}, + "outputs": [], + "source": [ + "# Define a function to call the optimization process and return the generated codes.\n", + "\n", + "def optimize(python_code, module_name, model):\n", + " \"\"\"Call the optimization process and return the generated codes.\"\"\"\n", + " optimization = optimize_gpt(python_code, module_name, model)\n", + " return optimization.c_code, optimization.setup, optimization.usage" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "19bf2bff-a822-4009-a539-f003b1651383", + "metadata": {}, + "outputs": [], + "source": [ + "# Define a function to execute Python code and capture its output.\n", + "\n", + "def execute_python(code):\n", + " \"\"\"Execute the given Python code and capture its output.\"\"\"\n", + " try:\n", + " output = io.StringIO()\n", + " sys.stdout = output\n", + " exec(code)\n", + " finally:\n", + " sys.stdout = sys.__stdout__\n", + " return output.getvalue()" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "5fd83307", + "metadata": {}, + "outputs": [], + "source": [ + "# Extension compilation function.\n", + "\n", + "def build_extension():\n", + " \"\"\"Compile the C extension using 'setup.py' and return the compilation output.\"\"\"\n", + " # Set default COMSPEC to cmd.exe on Windows to avoid issues with some C compilers.\n", + " preset_comspec = os.environ.get(\"COMSPEC\")\n", + " os.environ[\"COMSPEC\"] = \"C:\\\\Windows\\\\System32\\\\cmd.exe\"\n", + " try:\n", + " compile_cmd = [\"python\", \"setup.py\", \"build_ext\", \"--inplace\"]\n", + " compile_result = subprocess.run(compile_cmd, env=os.environ,\n", + " check=True, text=True, capture_output=True)\n", + " except subprocess.CalledProcessError as ex:\n", + " raise Exception(f\"An error occurred while building:\\n{ex.stdout}\\n{ex.stderr}\")\n", + " finally: # The 'finally' clauses executes always whether there was an exception or not.\n", + " # Restore original COMSPEC.\n", + " os.environ[\"COMSPEC\"] = preset_comspec\n", + " return compile_result.stdout" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "77f3ab5d-fcfb-4d3f-8728-9cacbf833ea6", + "metadata": {}, + "outputs": [], + "source": [ + "# Extension compilation function.\n", + "\n", + "def generate_extension(c_code, setup_code, usage_code, module_name):\n", + " \"\"\"Build and install the C extension from the provided codes.\"\"\"\n", + " try: # Write the provided codes to their respective files.\n", + " write_file(c_code, f\"{module_name}.c\")\n", + " write_file(setup_code, \"setup.py\")\n", + " except Exception as ex:\n", + " return f\"An error occurred while writing files:\\n{ex}\"\n", + " # Build the extension and capture the output.\n", + " try:\n", + " build_output = build_extension()\n", + " except Exception as ex: # If build fails, return the error message.\n", + " return str(ex)\n", + " # Return the combined output of build and install processes.\n", + " return build_output" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "51f78871", + "metadata": {}, + "outputs": [], + "source": [ + "# Extension testing function.\n", + "\n", + "def test_extension(usage_code):\n", + " \"\"\"Test the installed C extension by executing the provided usage code and capturing its output.\"\"\"\n", + " try: # Write the provided codes to their respective files.\n", + " write_file(usage_code, \"usage_example.py\")\n", + " except Exception as ex:\n", + " return f\"An error occurred while writing test file:\\n{ex}\"\n", + " try:\n", + " output = execute_python(usage_code)\n", + " except Exception as ex:\n", + " return f\"An error occurred while testing the extension:\\n{ex}\"\n", + " return output" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "9a2274f1-d03b-42c0-8dcc-4ce159b18442", + "metadata": {}, + "outputs": [], + "source": [ + "# Define custom CSS for Gradio interface.\n", + "\n", + "css = \"\"\"\n", + ".python {background-color: #306998;}\n", + ".c_ext {background-color: #050;}\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "c7c8f5fc", + "metadata": {}, + "outputs": [], + "source": [ + "# Define default codes for the interface.\n", + "\n", + "default_p_code = \"\"\"\n", + "def hello_world():\n", + " print(\"Hello, World!\")\n", + "\"\"\"\n", + "# default_p_code = python_hard_code # Run the declaration cell before use.\n", + "# default_p_code = calculate_pi_code # Run the declaration cell before use.\n", + "\n", + "default_c_code = r\"\"\"\n", + "#include \n", + "\n", + "// Function to be called from Python\n", + "static PyObject* zz_hello_world(PyObject* self, PyObject* args) {\n", + " printf(\"Hello, World!\\n\");\n", + " Py_RETURN_NONE;\n", + "}\n", + "\n", + "// Method definition structure\n", + "static PyMethodDef zz_my_methods[] = {\n", + " {\"hello_world\", zz_hello_world, METH_VARARGS, \"Print 'Hello, World!'\"},\n", + " {NULL, NULL, 0, NULL} // Sentinel\n", + "};\n", + "\n", + "// Module definition\n", + "static struct PyModuleDef zz_my_module = {\n", + " PyModuleDef_HEAD_INIT,\n", + " \"zz_my_module\",\n", + " \"Extension module that prints Hello, World!\",\n", + " -1,\n", + " zz_my_methods\n", + "};\n", + "\n", + "// Module initialization function\n", + "PyMODINIT_FUNC PyInit_zz_my_module(void) {\n", + " return PyModule_Create(&zz_my_module);\n", + "}\n", + "\"\"\"\n", + "\n", + "default_setup = \"\"\"\n", + "from setuptools import setup, Extension\n", + "\n", + "module = Extension(\n", + " 'zz_my_module',\n", + " sources=['zz_my_module.c'],\n", + ")\n", + "\n", + "setup(\n", + " name='zz_my_module',\n", + " version='1.0',\n", + " description='This is a custom C extension module.',\n", + " ext_modules=[module]\n", + ")\n", + "\"\"\"\n", + "\n", + "default_test = \"\"\"\n", + "import time\n", + "import zz_my_module\n", + "\n", + "def python_hello_world():\n", + " print(\"Hello, World!\")\n", + "\n", + "start = time.time()\n", + "python_hello_world()\n", + "end = time.time()\n", + "print(f\"Python function execution time: {end - start:.6f} seconds\")\n", + "\n", + "start = time.time()\n", + "zz_my_module.hello_world()\n", + "end = time.time()\n", + "print(f\"C extension execution time: {end - start:.6f} seconds\")\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "fa64577a", + "metadata": {}, + "outputs": [], + "source": [ + "# We will use gradio auto reload feature, this way we do not need to restart the app to see changes in the code.\n", + "# * https://www.gradio.app/guides/developing-faster-with-reload-mode\n", + "\n", + "%load_ext gradio\n", + "\n", + "# This mandatory requires naming the 'gr.Blocks' interface as 'demo'.\n", + "# Now, each time we edit the code, we just need to re-run Gradio interface cell to see the changes in the app.\n", + "# The '.launch()' method is not needed anymore." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f1303932-160c-424b-97a8-d28c816721b2", + "metadata": {}, + "outputs": [], + "source": [ + "%%blocks\n", + "\n", + "with gr.Blocks(css=css) as demo:\n", + " gr.Markdown(\"## Convert code from Python to C++\")\n", + " with gr.Row():\n", + " module_name = gr.Textbox(label=\"Module name:\", lines=1, value=\"zz_my_module\")\n", + " model = gr.Dropdown([\"gpt-4o\", \"gpt-5\"], label=\"Select model\", value=\"gpt-4o\")\n", + " with gr.Row():\n", + " python = gr.Textbox(label=\"Python code:\", lines=30, value=default_p_code, elem_classes=[\"python\"])\n", + " c_code = gr.Textbox(label=\"C Extension code:\", lines=30, value=default_c_code, elem_classes=[\"c_ext\"])\n", + " with gr.Row():\n", + " get_extension = gr.Button(\"Generate extension code\")\n", + " with gr.Row():\n", + " setup_code = gr.Textbox(label=\"Compilation code:\", lines=10, value=default_setup, elem_classes=[\"python\"])\n", + " usage_code = gr.Textbox(label=\"Test compare code:\", lines=10, value=default_test, elem_classes=[\"python\"])\n", + " with gr.Row():\n", + " compile_ext = gr.Button(\"Compile extension\")\n", + " with gr.Row():\n", + " c_ext_out = gr.TextArea(label=\"C Extension result:\", elem_classes=[\"c_ext\"])\n", + " with gr.Row():\n", + " test_run = gr.Button(\"Test code\")\n", + " with gr.Row():\n", + " test_out = gr.TextArea(label=\"Test result:\", elem_classes=[\"python\"])\n", + "\n", + " get_extension.click(optimize, inputs=[python, module_name, model], outputs=[c_code, setup_code, usage_code])\n", + " compile_ext.click(generate_extension, inputs=[c_code, setup_code, usage_code, module_name ], outputs=[c_ext_out])\n", + " test_run.click(test_extension, inputs=[usage_code], outputs=[test_out])\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "llm-engineering-pYAzjokc", + "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.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 78a3ee10b234f292421bf79844ea8d3b956bb961 Mon Sep 17 00:00:00 2001 From: Carlos Bazaga Date: Mon, 1 Sep 2025 01:37:59 +0200 Subject: [PATCH 2/5] Added sample files generated on the three different scenarios. Including C code, setup.py and run example code for: * Pi calculation with Leibniz formula. * Max sub-array calculation. (Aka: Python Hard) * Default for Gradio: Hello world. (Aka: _zz_my_module) --- .../c_extension_generator/calculate_pi.c | 83 ++++++ .../c_extension_generator/python_hard.c | 244 ++++++++++++++++++ .../setup_calculate_pi.py | 25 ++ .../setup_python_hard.py | 25 ++ .../setup_zz_my_module.py | 14 + .../usage_example_calculate_pi.py | 38 +++ .../usage_example_python_hard.py | 69 +++++ .../usage_example_zz_my_module.py | 16 ++ .../c_extension_generator/zz_my_module.c | 28 ++ 9 files changed, 542 insertions(+) create mode 100644 week4/community-contributions/c_extension_generator/calculate_pi.c create mode 100644 week4/community-contributions/c_extension_generator/python_hard.c create mode 100644 week4/community-contributions/c_extension_generator/setup_calculate_pi.py create mode 100644 week4/community-contributions/c_extension_generator/setup_python_hard.py create mode 100644 week4/community-contributions/c_extension_generator/setup_zz_my_module.py create mode 100644 week4/community-contributions/c_extension_generator/usage_example_calculate_pi.py create mode 100644 week4/community-contributions/c_extension_generator/usage_example_python_hard.py create mode 100644 week4/community-contributions/c_extension_generator/usage_example_zz_my_module.py create mode 100644 week4/community-contributions/c_extension_generator/zz_my_module.c diff --git a/week4/community-contributions/c_extension_generator/calculate_pi.c b/week4/community-contributions/c_extension_generator/calculate_pi.c new file mode 100644 index 0000000..c0b7f03 --- /dev/null +++ b/week4/community-contributions/c_extension_generator/calculate_pi.c @@ -0,0 +1,83 @@ +#define PY_SSIZE_T_CLEAN +#include +#include +#include +#include +#include + +static PyObject* leibniz_pi(PyObject* self, PyObject* args) { + PyObject* iterations_obj; + if (!PyArg_ParseTuple(args, "O", &iterations_obj)) { + return NULL; + } + + long long n_signed; + int overflow = 0; + n_signed = PyLong_AsLongLongAndOverflow(iterations_obj, &overflow); + if (n_signed == -1 && PyErr_Occurred() && overflow == 0) { + return NULL; + } + + unsigned long long n = 0ULL; + if (overflow < 0) { + n = 0ULL; + } else if (overflow > 0) { + unsigned long long tmp = PyLong_AsUnsignedLongLong(iterations_obj); + if (tmp == (unsigned long long)-1 && PyErr_Occurred()) { + return NULL; + } + n = tmp; + } else { + if (n_signed <= 0) { + n = 0ULL; + } else { + n = (unsigned long long)n_signed; + } + } + + double result = 1.0; + if (n == 0ULL) { + return PyFloat_FromDouble(result * 4.0); + } + + Py_BEGIN_ALLOW_THREADS + for (unsigned long long i = 1ULL; i <= n; ++i) { + double jd1; + if (i <= ULLONG_MAX / 4ULL) { + unsigned long long j1 = i * 4ULL - 1ULL; + jd1 = (double)j1; + } else { + jd1 = (double)i * 4.0 - 1.0; + } + result -= 1.0 / jd1; + + double jd2; + if (i <= (ULLONG_MAX - 1ULL) / 4ULL) { + unsigned long long j2 = i * 4ULL + 1ULL; + jd2 = (double)j2; + } else { + jd2 = (double)i * 4.0 + 1.0; + } + result += 1.0 / jd2; + } + Py_END_ALLOW_THREADS + + return PyFloat_FromDouble(result * 4.0); +} + +static PyMethodDef CalculatePiMethods[] = { + {"leibniz_pi", leibniz_pi, METH_VARARGS, "Compute pi using the Leibniz series with the given number of iterations."}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef calculate_pimodule = { + PyModuleDef_HEAD_INIT, + "calculate_pi", + "High-performance Leibniz pi calculation.", + -1, + CalculatePiMethods +}; + +PyMODINIT_FUNC PyInit_calculate_pi(void) { + return PyModule_Create(&calculate_pimodule); +} diff --git a/week4/community-contributions/c_extension_generator/python_hard.c b/week4/community-contributions/c_extension_generator/python_hard.c new file mode 100644 index 0000000..67968ea --- /dev/null +++ b/week4/community-contributions/c_extension_generator/python_hard.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include + +// LCG step with 32-bit wrap-around +static inline uint32_t lcg_next(uint32_t *state) { + *state = (uint32_t)(1664525u * (*state) + 1013904223u); + return *state; +} + +static inline int add_overflow_int64(int64_t a, int64_t b, int64_t *res) { + if ((b > 0 && a > INT64_MAX - b) || (b < 0 && a < INT64_MIN - b)) return 1; + *res = a + b; + return 0; +} + +// Kadane for int64 array with overflow detection; returns PyLong or NULL (on overflow -> signal via *overflowed) +static PyObject* kadane_int64(const int64_t *arr, Py_ssize_t n, int *overflowed) { + if (n <= 0) { + return PyFloat_FromDouble(-INFINITY); + } + int64_t meh = arr[0]; + int64_t msf = arr[0]; + for (Py_ssize_t i = 1; i < n; ++i) { + int64_t x = arr[i]; + if (meh > 0) { + int64_t tmp; + if (add_overflow_int64(meh, x, &tmp)) { *overflowed = 1; return NULL; } + meh = tmp; + } else { + meh = x; + } + if (meh > msf) msf = meh; + } + return PyLong_FromLongLong(msf); +} + +// Kadane for PyObject* integer array +static PyObject* kadane_big(PyObject **arr, Py_ssize_t n) { + if (n <= 0) { + return PyFloat_FromDouble(-INFINITY); + } + PyObject *meh = arr[0]; Py_INCREF(meh); + PyObject *msf = arr[0]; Py_INCREF(msf); + PyObject *zero = PyLong_FromLong(0); + if (!zero) { Py_DECREF(meh); Py_DECREF(msf); return NULL; } + + for (Py_ssize_t i = 1; i < n; ++i) { + int cmp = PyObject_RichCompareBool(meh, zero, Py_GT); + if (cmp < 0) { Py_DECREF(meh); Py_DECREF(msf); Py_DECREF(zero); return NULL; } + if (cmp == 1) { + PyObject *t = PyNumber_Add(meh, arr[i]); + if (!t) { Py_DECREF(meh); Py_DECREF(msf); Py_DECREF(zero); return NULL; } + Py_DECREF(meh); + meh = t; + } else { + Py_DECREF(meh); + meh = arr[i]; Py_INCREF(meh); + } + int cmp2 = PyObject_RichCompareBool(meh, msf, Py_GT); + if (cmp2 < 0) { Py_DECREF(meh); Py_DECREF(msf); Py_DECREF(zero); return NULL; } + if (cmp2 == 1) { + Py_DECREF(msf); + msf = meh; Py_INCREF(msf); + } + } + Py_DECREF(meh); + Py_DECREF(zero); + return msf; // new reference +} + +// Generate int64 array fast path; returns 0 on success +static int gen_array_int64(Py_ssize_t n, uint32_t seed, int64_t min_v, int64_t max_v, int64_t *out) { + uint32_t state = seed; + uint64_t umax = (uint64_t)max_v; + uint64_t umin = (uint64_t)min_v; + uint64_t range = (umax - umin) + 1ULL; // max>=min guaranteed by caller + for (Py_ssize_t i = 0; i < n; ++i) { + state = lcg_next(&state); + uint32_t r32 = state; + uint64_t r = (range > 0x100000000ULL) ? (uint64_t)r32 : ((uint64_t)r32 % range); + int64_t val = (int64_t)(min_v + (int64_t)r); + out[i] = val; + } + return 0; +} + +// Generate PyObject* int array general path using Python arithmetic +static PyObject** gen_array_big(Py_ssize_t n, uint32_t seed, PyObject *min_val, PyObject *max_val) { + PyObject **arr = (PyObject**)PyMem_Malloc((n > 0 ? n : 1) * sizeof(PyObject*)); + if (!arr) { + PyErr_NoMemory(); + return NULL; + } + PyObject *one = PyLong_FromLong(1); + if (!one) { PyMem_Free(arr); return NULL; } + PyObject *diff = PyNumber_Subtract(max_val, min_val); + if (!diff) { Py_DECREF(one); PyMem_Free(arr); return NULL; } + PyObject *range_obj = PyNumber_Add(diff, one); + Py_DECREF(diff); + Py_DECREF(one); + if (!range_obj) { PyMem_Free(arr); return NULL; } + + uint32_t state = seed; + for (Py_ssize_t i = 0; i < n; ++i) { + state = lcg_next(&state); + PyObject *v = PyLong_FromUnsignedLong((unsigned long)state); + if (!v) { + Py_DECREF(range_obj); + for (Py_ssize_t k = 0; k < i; ++k) Py_DECREF(arr[k]); + PyMem_Free(arr); + return NULL; + } + PyObject *r = PyNumber_Remainder(v, range_obj); + Py_DECREF(v); + if (!r) { + Py_DECREF(range_obj); + for (Py_ssize_t k = 0; k < i; ++k) Py_DECREF(arr[k]); + PyMem_Free(arr); + return NULL; + } + PyObject *val = PyNumber_Add(r, min_val); + Py_DECREF(r); + if (!val) { + Py_DECREF(range_obj); + for (Py_ssize_t k = 0; k < i; ++k) Py_DECREF(arr[k]); + PyMem_Free(arr); + return NULL; + } + arr[i] = val; + } + Py_DECREF(range_obj); + return arr; +} + +static PyObject* max_subarray_sum_internal(Py_ssize_t n, uint32_t seed, PyObject *min_val, PyObject *max_val) { + if (n <= 0) { + return PyFloat_FromDouble(-INFINITY); + } + + if (PyLong_Check(min_val) && PyLong_Check(max_val)) { + int overflow1 = 0, overflow2 = 0; + long long min64 = PyLong_AsLongLongAndOverflow(min_val, &overflow1); + if (overflow1) goto BIGINT_PATH; + long long max64 = PyLong_AsLongLongAndOverflow(max_val, &overflow2); + if (overflow2) goto BIGINT_PATH; + if (max64 >= min64) { + int64_t *arr = (int64_t*)PyMem_Malloc((size_t)n * sizeof(int64_t)); + if (!arr) { PyErr_NoMemory(); return NULL; } + if (gen_array_int64(n, seed, (int64_t)min64, (int64_t)max64, arr) != 0) { + PyMem_Free(arr); + return NULL; + } + int overflowed = 0; + PyObject *res = kadane_int64(arr, n, &overflowed); + if (!res && overflowed) { + // fallback to big-int Kadane + PyObject **arr_obj = (PyObject**)PyMem_Malloc((size_t)n * sizeof(PyObject*)); + if (!arr_obj) { PyMem_Free(arr); PyErr_NoMemory(); return NULL; } + for (Py_ssize_t i = 0; i < n; ++i) { + arr_obj[i] = PyLong_FromLongLong(arr[i]); + if (!arr_obj[i]) { + for (Py_ssize_t k = 0; k < i; ++k) Py_DECREF(arr_obj[k]); + PyMem_Free(arr_obj); + PyMem_Free(arr); + return NULL; + } + } + PyObject *bires = kadane_big(arr_obj, n); + for (Py_ssize_t i = 0; i < n; ++i) Py_DECREF(arr_obj[i]); + PyMem_Free(arr_obj); + PyMem_Free(arr); + return bires; + } + PyMem_Free(arr); + return res; + } + } +BIGINT_PATH: ; + PyObject **arr_obj = gen_array_big(n, seed, min_val, max_val); + if (!arr_obj) return NULL; + PyObject *res = kadane_big(arr_obj, n); + for (Py_ssize_t i = 0; i < n; ++i) Py_DECREF(arr_obj[i]); + PyMem_Free(arr_obj); + return res; +} + +static PyObject* py_max_subarray_sum(PyObject *self, PyObject *args) { + Py_ssize_t n; + PyObject *seed_obj, *min_val, *max_val; + if (!PyArg_ParseTuple(args, "nOOO", &n, &seed_obj, &min_val, &max_val)) return NULL; + if (n < 0) n = 0; + uint32_t seed = (uint32_t)(PyLong_AsUnsignedLongLongMask(seed_obj) & 0xFFFFFFFFULL); + if (PyErr_Occurred()) return NULL; + return max_subarray_sum_internal(n, seed, min_val, max_val); +} + +static PyObject* py_total_max_subarray_sum(PyObject *self, PyObject *args) { + Py_ssize_t n; + PyObject *init_seed_obj, *min_val, *max_val; + if (!PyArg_ParseTuple(args, "nOOO", &n, &init_seed_obj, &min_val, &max_val)) return NULL; + if (n < 0) n = 0; + uint32_t state = (uint32_t)(PyLong_AsUnsignedLongLongMask(init_seed_obj) & 0xFFFFFFFFULL); + if (PyErr_Occurred()) return NULL; + + PyObject *total = PyLong_FromLong(0); + if (!total) return NULL; + + for (int i = 0; i < 20; ++i) { + uint32_t seed = lcg_next(&state); + PyObject *part = max_subarray_sum_internal(n, seed, min_val, max_val); + if (!part) { Py_DECREF(total); return NULL; } + PyObject *new_total = PyNumber_Add(total, part); + Py_DECREF(part); + if (!new_total) { Py_DECREF(total); return NULL; } + Py_DECREF(total); + total = new_total; + } + return total; +} + +static PyMethodDef module_methods[] = { + {"max_subarray_sum", (PyCFunction)py_max_subarray_sum, METH_VARARGS, "Compute maximum subarray sum using LCG-generated array."}, + {"total_max_subarray_sum", (PyCFunction)py_total_max_subarray_sum, METH_VARARGS, "Compute total of maximum subarray sums over 20 LCG seeds."}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "python_hard", + NULL, + -1, + module_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC PyInit_python_hard(void) { + return PyModule_Create(&moduledef); +} diff --git a/week4/community-contributions/c_extension_generator/setup_calculate_pi.py b/week4/community-contributions/c_extension_generator/setup_calculate_pi.py new file mode 100644 index 0000000..ecb4067 --- /dev/null +++ b/week4/community-contributions/c_extension_generator/setup_calculate_pi.py @@ -0,0 +1,25 @@ +from setuptools import setup, Extension +import sys +import os + +extra_compile_args = [] +extra_link_args = [] + +if os.name == 'nt': + extra_compile_args.extend(['/O2', '/fp:precise']) +else: + extra_compile_args.extend(['-O3', '-fno-strict-aliasing']) + +module = Extension( + 'calculate_pi', + sources=['calculate_pi.c'], + extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args, +) + +setup( + name='calculate_pi', + version='1.0.0', + description='High-performance C extension for computing pi via the Leibniz series', + ext_modules=[module], +) diff --git a/week4/community-contributions/c_extension_generator/setup_python_hard.py b/week4/community-contributions/c_extension_generator/setup_python_hard.py new file mode 100644 index 0000000..20d3d3f --- /dev/null +++ b/week4/community-contributions/c_extension_generator/setup_python_hard.py @@ -0,0 +1,25 @@ +from setuptools import setup, Extension +import sys + +extra_compile_args = [] +extra_link_args = [] +if sys.platform == 'win32': + extra_compile_args = ['/O2', '/Ot', '/GL', '/fp:fast'] + extra_link_args = ['/LTCG'] +else: + extra_compile_args = ['-O3', '-march=native'] + +module = Extension( + name='python_hard', + sources=['python_hard.c'], + extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args, + language='c' +) + +setup( + name='python_hard', + version='1.0.0', + description='High-performance C extension reimplementation', + ext_modules=[module] +) diff --git a/week4/community-contributions/c_extension_generator/setup_zz_my_module.py b/week4/community-contributions/c_extension_generator/setup_zz_my_module.py new file mode 100644 index 0000000..bb0d27b --- /dev/null +++ b/week4/community-contributions/c_extension_generator/setup_zz_my_module.py @@ -0,0 +1,14 @@ + +from setuptools import setup, Extension + +module = Extension( + 'zz_my_module', + sources=['zz_my_module.c'], +) + +setup( + name='zz_my_module', + version='1.0', + description='This is a custom C extension module.', + ext_modules=[module] +) diff --git a/week4/community-contributions/c_extension_generator/usage_example_calculate_pi.py b/week4/community-contributions/c_extension_generator/usage_example_calculate_pi.py new file mode 100644 index 0000000..c3cc418 --- /dev/null +++ b/week4/community-contributions/c_extension_generator/usage_example_calculate_pi.py @@ -0,0 +1,38 @@ +# Build first: python setup.py build_ext --inplace +import time +import math +import calculate_pi + +# Original Python implementation +def py_leibniz_pi(iterations): + result = 1.0 + for i in range(1, iterations + 1): + j = i * 4 - 1 + result -= (1 / j) + j = i * 4 + 1 + result += (1 / j) + return result * 4 + +iters = 5_000_000 + +# Warm-up +calculate_pi.leibniz_pi(10) +py_leibniz_pi(10) + +start = time.perf_counter() +res_c = calculate_pi.leibniz_pi(iters) +end = time.perf_counter() +ctime = end - start + +start = time.perf_counter() +res_py = py_leibniz_pi(iters) +end = time.perf_counter() +pytime = end - start + +print(f"Iterations: {iters}") +print(f"C extension result: {res_c}") +print(f"Python result: {res_py}") +print(f"Absolute difference: {abs(res_c - res_py)}") +print(f"C extension time: {ctime:.6f} s") +print(f"Python time: {pytime:.6f} s") +print(f"Speedup: {pytime/ctime if ctime > 0 else float('inf'):.2f}x") diff --git a/week4/community-contributions/c_extension_generator/usage_example_python_hard.py b/week4/community-contributions/c_extension_generator/usage_example_python_hard.py new file mode 100644 index 0000000..552b0b5 --- /dev/null +++ b/week4/community-contributions/c_extension_generator/usage_example_python_hard.py @@ -0,0 +1,69 @@ +import time + +# Original Python code + +def lcg(seed, a=1664525, c=1013904223, m=2**32): + value = seed + while True: + value = (a * value + c) % m + yield value + +def max_subarray_sum_py(n, seed, min_val, max_val): + lcg_gen = lcg(seed) + random_numbers = [next(lcg_gen) % (max_val - min_val + 1) + min_val for _ in range(n)] + max_sum = float('-inf') + for i in range(n): + current_sum = 0 + for j in range(i, n): + current_sum += random_numbers[j] + if current_sum > max_sum: + max_sum = current_sum + return max_sum + +def total_max_subarray_sum_py(n, initial_seed, min_val, max_val): + total_sum = 0 + lcg_gen = lcg(initial_seed) + for _ in range(20): + seed = next(lcg_gen) + total_sum += max_subarray_sum_py(n, seed, min_val, max_val) + return total_sum + +# Build and import extension (after running: python setup.py build && install or develop) +import python_hard as ext + +# Example parameters +n = 600 +initial_seed = 12345678901234567890 +min_val = -1000 +max_val = 1000 + +# Time Python +t0 = time.perf_counter() +py_res1 = max_subarray_sum_py(n, (initial_seed * 1664525 + 1013904223) % (2**32), min_val, max_val) +t1 = time.perf_counter() +py_time1 = t1 - t0 + +# Time C extension +t0 = time.perf_counter() +ext_res1 = ext.max_subarray_sum(n, (initial_seed * 1664525 + 1013904223) % (2**32), min_val, max_val) +t1 = time.perf_counter() +ext_time1 = t1 - t0 + +print('max_subarray_sum equality:', py_res1 == ext_res1) +print('Python time:', py_time1) +print('C ext time:', ext_time1) + +# Total over 20 seeds +t0 = time.perf_counter() +py_res2 = total_max_subarray_sum_py(n, initial_seed, min_val, max_val) +t1 = time.perf_counter() +py_time2 = t1 - t0 + +t0 = time.perf_counter() +ext_res2 = ext.total_max_subarray_sum(n, initial_seed, min_val, max_val) +t1 = time.perf_counter() +ext_time2 = t1 - t0 + +print('total_max_subarray_sum equality:', py_res2 == ext_res2) +print('Python total time:', py_time2) +print('C ext total time:', ext_time2) diff --git a/week4/community-contributions/c_extension_generator/usage_example_zz_my_module.py b/week4/community-contributions/c_extension_generator/usage_example_zz_my_module.py new file mode 100644 index 0000000..6404cd3 --- /dev/null +++ b/week4/community-contributions/c_extension_generator/usage_example_zz_my_module.py @@ -0,0 +1,16 @@ + +import time +import zz_my_module + +def python_hello_world(): + print("Hello, World!") + +start = time.time() +python_hello_world() +end = time.time() +print(f"Python function execution time: {end - start:.6f} seconds") + +start = time.time() +zz_my_module.hello_world() +end = time.time() +print(f"C extension execution time: {end - start:.6f} seconds") diff --git a/week4/community-contributions/c_extension_generator/zz_my_module.c b/week4/community-contributions/c_extension_generator/zz_my_module.c new file mode 100644 index 0000000..2593233 --- /dev/null +++ b/week4/community-contributions/c_extension_generator/zz_my_module.c @@ -0,0 +1,28 @@ + +#include + +// Function to be called from Python +static PyObject* zz_hello_world(PyObject* self, PyObject* args) { + printf("Hello, World!\n"); + Py_RETURN_NONE; +} + +// Method definition structure +static PyMethodDef zz_my_methods[] = { + {"hello_world", zz_hello_world, METH_VARARGS, "Print 'Hello, World!'"}, + {NULL, NULL, 0, NULL} // Sentinel +}; + +// Module definition +static struct PyModuleDef zz_my_module = { + PyModuleDef_HEAD_INIT, + "zz_my_module", + "Extension module that prints Hello, World!", + -1, + zz_my_methods +}; + +// Module initialization function +PyMODINIT_FUNC PyInit_zz_my_module(void) { + return PyModule_Create(&zz_my_module); +} From 23856653adc4b1e7df4684971e729113ca70263d Mon Sep 17 00:00:00 2001 From: Carlos Bazaga Date: Mon, 1 Sep 2025 02:20:46 +0200 Subject: [PATCH 3/5] Added README.md describing Gradio app. --- .../c_extension_generator/README.md | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 week4/community-contributions/c_extension_generator/README.md diff --git a/week4/community-contributions/c_extension_generator/README.md b/week4/community-contributions/c_extension_generator/README.md new file mode 100644 index 0000000..92df278 --- /dev/null +++ b/week4/community-contributions/c_extension_generator/README.md @@ -0,0 +1,131 @@ +# Python C Extension code generator + +This folder contains a Jupyter notebook that demonstrates how to use a Frontier model +to generate high-performance Python C extension code from Python code. + +The notebook includes examples of generating C extensions for calculating Pi using the +Leibniz formula and finding the maximum sub-array in an array. + +Also, it includes a Gradio app that provides an interactive interface for users to input +Python code, generate C extension code, compile it, and test its performance against +the original Python code. + +> [!CAUTION] +> +> **Always review the generated codes before running them, as they will be executed in +> your local environment and may contain code that could be harmful or unwanted.** +> +> AI-generated code may contain errors or unsafe practices, so it's crucial to +> thoroughly review and test any code before using it in a production environment. +> +> Never run code generated by AI models without understanding its implications and +> ensuring it adheres to your security and safety standards. + +> [!IMPORTANT] +> +> **Disclaimer:** This notebook and the Gradio app are provided for educational purposes +> only. Use them at your own risk. + +## Gradio app overview + +In this image, you can see the Gradio app dashboard whose main sections are +described below. + +![Gradio app dashboard](gradio_dashboard.png)\ +*Image: Gradio app dashboard with default example `hello world` code loaded.* +*(compile output redacted for privacy)* + +Sections: + +* **Dropdown selectors and input fields**: + * **Module name input**: + A text input field where users can specify the name of the C extension module to be + generated. + + That name will be used to create the C extension file `.c` and + the `setup.py` file required to compile the extension. + + That name will also be used to import the compiled module as usual in Python: + + ```python + import + ``` + + Or + + ```python + from import + ``` + + * **Model selector**: + A dropdown menu to select the Frontier model to use for code generation. + + Currently it includes: + * `gpt-4o` (default) + * `gpt-5` + +* **Text input areas**: + + This areas are all editable, included those filled with generated code by the model. + this allows users to modify and experiment with the code as needed. + + * **Python code**: + A text area where users can input their Python code. + * **C extension code**: + A text area that displays the generated C extension code and allows to edit it. + * **Compilation code**: + A text area that shows the `setup.py` file generated, + this file is required to compile the C extension. + * **Test compare code**: + A text area that provides example code to run the compiled C extension. + +* **Output areas**: + + This are non-editable areas that display the results of various operations. + + * **C Extension result**: + A text area that displays the output of the C extension code build. + + Beware that this area can contain a large amount of text including warnings during + the compilation process and sensible information about the local environment, + like: paths, Python version, etc may be included. + + Redact that information if you plan to share the output. + + * **Test result**: + A text area that displays the output of the test code run. + +* **Buttons**: + * **Generate extension code**: + A button that triggers the generation of the C extension code from the provided + Python code. + + It will call the Frontier model to generate the C code, the setup.py file and + the test code, filling the corresponding text areas automatically. + + * **Compile extension**: + A button that compiles the generated C extension using the provided `setup.py` file. + It will create the extension c file, `.c` and the `setup.py` files in + the local folder, then it will run the compilation command and build the C extension. + + > [!CAUTION] + > + > **Always review the `setup.py` code before running it, as it will be executed in + > your local environment and may contain code that could be harmful or unwanted.** + > + > **Also review the generated C code, as it will be compiled and executed in your + > local environment and may contain code that could be harmful or unwanted.** + + It will display the compilation output in the "C Extension result" area. + + * **Test code**: + A button that executes the test code to compare the performance of the original + Python code and the generated C extension. + + > [!CAUTION] + > + > **Always review the test code before running it, as it will be executed in + > your local environment and may contain code that could be harmful or unwanted.** + + Will save the test code provided in the "Test compare code" into the + `usage_example.py` file and execute it showing the output in the "Test result" area. From 86ae3b9a1ee3c22af6d9b0db674bc9bf0ced7d24 Mon Sep 17 00:00:00 2001 From: Carlos Bazaga Date: Mon, 1 Sep 2025 02:25:02 +0200 Subject: [PATCH 4/5] Added dashboard image as .jpg and updated README. Why are .png files ignored??? --- .../c_extension_generator/README.md | 2 +- .../c_extension_generator/gradio_dashboard.jpg | Bin 0 -> 248822 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 week4/community-contributions/c_extension_generator/gradio_dashboard.jpg diff --git a/week4/community-contributions/c_extension_generator/README.md b/week4/community-contributions/c_extension_generator/README.md index 92df278..54d2a7a 100644 --- a/week4/community-contributions/c_extension_generator/README.md +++ b/week4/community-contributions/c_extension_generator/README.md @@ -31,7 +31,7 @@ the original Python code. In this image, you can see the Gradio app dashboard whose main sections are described below. -![Gradio app dashboard](gradio_dashboard.png)\ +![Gradio app dashboard](gradio_dashboard.jpg)\ *Image: Gradio app dashboard with default example `hello world` code loaded.* *(compile output redacted for privacy)* diff --git a/week4/community-contributions/c_extension_generator/gradio_dashboard.jpg b/week4/community-contributions/c_extension_generator/gradio_dashboard.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7b076897c5b465fe2cd5c26260ecd4c0bcc1ea36 GIT binary patch literal 248822 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¥?{r-hE> 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 literal 0 HcmV?d00001 From f10c9de5d4f2915c0add9aba1421de82ba3fd454 Mon Sep 17 00:00:00 2001 From: Carlos Bazaga Date: Mon, 1 Sep 2025 02:35:33 +0200 Subject: [PATCH 5/5] Added license and authorship. --- .../c_extension_generator/LICENSE | 21 +++++++++++++++++++ .../c_extension_generator/README.md | 3 +++ 2 files changed, 24 insertions(+) create mode 100644 week4/community-contributions/c_extension_generator/LICENSE diff --git a/week4/community-contributions/c_extension_generator/LICENSE b/week4/community-contributions/c_extension_generator/LICENSE new file mode 100644 index 0000000..0ca1b61 --- /dev/null +++ b/week4/community-contributions/c_extension_generator/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Carlos Bazaga + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/week4/community-contributions/c_extension_generator/README.md b/week4/community-contributions/c_extension_generator/README.md index 54d2a7a..87d25db 100644 --- a/week4/community-contributions/c_extension_generator/README.md +++ b/week4/community-contributions/c_extension_generator/README.md @@ -1,5 +1,8 @@ # Python C Extension code generator +Written by Carlos Bazaga [@carbaz] based on the work of Ed Donner [@ed-donner] +under the MIT License. + This folder contains a Jupyter notebook that demonstrates how to use a Frontier model to generate high-performance Python C extension code from Python code.