Skip to main content

Framework for exploring advanced program synthesis and transformation techniques

Project description

NervaPy logo

NervaPy

NervaPy is a Python framework for writing high-performance assembly kernels.

NervaPy aims to simplify writing optimized assembly kernels while preserving all optimization opportunities of traditional assembly. Some NervaPy features:

  • Universal assembly syntax for Windows, Unix, and Golang assembly.

    • NervaPy can directly generate ELF, MS COFF and Mach-O object files and assembly listings for Golang toolchain

  • Automatic adaption of function to different calling conventions and ABIs.

    • Functions for different platforms can be generated from the same assembly source

    • Supports Microsoft x64 ABI, System V x86-64 ABI (Linux, OS X, and FreeBSD), Linux x32 ABI, Native Client x86-64 SFI ABI, Golang AMD64 ABI, Golang AMD64p32 ABI

  • Automatic register allocation.

    • NervaPy is flexible and lets mix auto-allocated and hardcoded registers in the same code.

  • Automation of routine tasks in assembly programming:

    • Function prolog and epilog and generated by NervaPy

    • De-duplication of data constants (e.g. Constant.float32x4(1.0))

    • Analysis of ISA extensions used in a function

  • Supports x86-64 instructions up to AVX-512 and SHA

    • Including 3dnow!+, XOP, FMA3, FMA4, TBM and BMI2.

    • Excluding x87 FPU and most system instructions.

  • Auto-generation of metadata files

    • Makefile with module dependencies (-MMD and -MF options)

    • C header for the generated functions

    • Function metadata in JSON format

  • Python-based metaprogramming and code-generation.

  • Multiplexing of multiple instruction streams (helpful for software pipelining).

  • Compatible with Python 2 and Python 3, CPython and PyPy.

Installation

NervaPy is actively developed, and thus there are presently no stable releases of 0.2 branch. We recommend that you use the master version:

pip install --upgrade git+https://github.com/kriskwiatkowski/NervaPy

Installation for development

If you plan to modify NervaPy, we recommend the following installation procedure:

git clone https://github.com/kriskwiatkowski/NervaPy.git
cd NervaPy
python setup.py develop

Using NervaPy as a command-line tool

# These two lines are not needed for NervaPy, but will help you get autocompletion in good code editors
from nervapy import *
from nervapy.x86_64 import *

# Lets write a function float DotProduct(const float* x, const float* y)

# If you want maximum cross-platform compatibility, arguments must have names
x = Argument(ptr(const_float_), name="x")
# If name is not specified, it is auto-detected
y = Argument(ptr(const_float_))

# Everything inside the `with` statement is function body
with Function("DotProduct", (x, y), float_,
  # Enable instructions up to SSE4.2
  # NervaPy will report error if you accidentally use a newer instruction
  target=uarch.default + isa.sse4_2):

  # Request two 64-bit general-purpose registers. No need to specify exact names.
  reg_x, reg_y = GeneralPurposeRegister64(), GeneralPurposeRegister64()

  # This is a cross-platform way to load arguments. NervaPy will map it to something proper later.
  LOAD.ARGUMENT(reg_x, x)
  LOAD.ARGUMENT(reg_y, y)

  # Also request a virtual 128-bit SIMD register...
  xmm_x = XMMRegister()
  # ...and fill it with data
  MOVAPS(xmm_x, [reg_x])
  # It is fine to mix virtual and physical (xmm0-xmm15) registers in the same code
  MOVAPS(xmm2, [reg_y])

  # Execute dot product instruction, put result into xmm_x
  DPPS(xmm_x, xmm2, 0xF1)

  # This is a cross-platform way to return results. NervaPy will take care of ABI specifics.
  RETURN(xmm_x)

Now you can compile this code into a binary object file that you can link into a program…

# Use MS-COFF format with Microsoft ABI for Windows
python -m nervapy.x86_64 -mabi=ms -mimage-format=ms-coff -o example.obj example.py
# Use Mach-O format with SysV ABI for OS X
python -m nervapy.x86_64 -mabi=sysv -mimage-format=mach-o -o example.o example.py
# Use ELF format with SysV ABI for Linux x86-64
python -m nervapy.x86_64 -mabi=sysv -mimage-format=elf -o example.o example.py
# Use ELF format with x32 ABI for Linux x32 (x86-64 with 32-bit pointer)
python -m nervapy.x86_64 -mabi=x32 -mimage-format=elf -o example.o example.py
# Use ELF format with Native Client x86-64 ABI for Chromium x86-64
python -m nervapy.x86_64 -mabi=nacl -mimage-format=elf -o example.o example.py

What else? You can convert the program to Plan 9 assembly for use with Go programming language:

# Use Go ABI (asm version) with -S flag to generate assembly for Go x86-64 targets
python -m nervapy.x86_64 -mabi=goasm -S -o example_amd64.s example.py
# Use Go-p32 ABI (asm version) with -S flag to generate assembly for Go x86-64 targets with 32-bit pointers
python -m nervapy.x86_64 -mabi=goasm-p32 -S -o example_amd64p32.s example.py

If Plan 9 assembly is too restrictive for your use-case, generate .syso objects which can be linked into Go programs:

# Use Go ABI (syso version) to generate .syso objects for Go x86-64 targets
# Image format can be any (ELF/Mach-O/MS-COFF)
python -m nervapy.x86_64 -mabi=gosyso -mimage-format=elf -o example_amd64.syso example.py
# Use Go-p32 ABI (syso version) to generate .syso objects for Go x86-64 targets with 32-bit pointers
# Image format can be any (ELF/Mach-O/MS-COFF)
python -m nervapy.x86_64 -mabi=gosyso-p32 -mimage-format=elf -o example_amd64p32.syso example.py

See examples for real-world scenarios of using NervaPy with make, nmake and go generate tools.

Using NervaPy as a Python module

When command-line tool does not provide sufficient flexibility, Python scripts can import NervaPy objects from nervapy and nervapy.x86_64 modules and do arbitrary manipulations on output images, program structure, instructions, and bytecodes.

NervaPy as Inline Assembler for Python

NervaPy links assembly and Python: it represents assembly instructions and syntax as Python classes, functions, and objects. But it also works the other way around: NervaPy can represent your assembly functions as callable Python functions!

from nervapy import *
from nervapy.x86_64 import *

x = Argument(int32_t)
y = Argument(int32_t)

with Function("Add", (x, y), int32_t) as asm_function:
    reg_x = GeneralPurposeRegister32()
    reg_y = GeneralPurposeRegister32()

    LOAD.ARGUMENT(reg_x, x)
    LOAD.ARGUMENT(reg_y, y)

    ADD(reg_x, reg_y)

    RETURN(reg_x)

python_function = asm_function.finalize(abi.detect()).encode().load()

print(python_function(2, 2)) # -> prints "4"

NervaPy as Instruction Encoder

NervaPy can be used to explore instruction length, opcodes, and alternative encodings:

from nervapy.x86_64 import *

ADD(eax, 5).encode() # -> bytearray(b'\x83\xc0\x05')

MOVAPS(xmm0, xmm1).encode_options() # -> [bytearray(b'\x0f(\xc1'), bytearray(b'\x0f)\xc8')]

VPSLLVD(ymm0, ymm1, [rsi + 8]).encode_length_options() # -> {6: bytearray(b'\xc4\xe2uGF\x08'),
                                                       #     7: bytearray(b'\xc4\xe2uGD&\x08'),
                                                       #     9: bytearray(b'\xc4\xe2uG\x86\x08\x00\x00\x00')}

Tutorials

Users

  • NNPACK – an acceleration layer for convolutional networks on multi-core CPUs.

  • ChaCha20 – Go implementation of ChaCha20 cryptographic cipher.

  • AEZ – Go implementation of AEZ authenticated-encryption scheme.

  • bp128 – Go implementation of SIMD-BP128 integer encoding and decoding.

  • go-marvin32 – Go implementation of Microsoft’s Marvin32 hash function.

  • go-highway – Go implementation of Google’s Highway hash function.

  • go-metro – Go implementation of MetroHash function.

  • go-stadtx – Go implementation of Stadtx hash function.

  • go-sip13 – Go implementation of SipHash 1-3 function.

  • go-chaskey – Go implementation of Chaskey MAC.

  • go-speck – Go implementation of SPECK cipher.

  • go-bloomindex - Go implementation of Bloom-filter based search index.

  • go-groupvariant - SSE-optimized group varint integer encoding in Go.

  • Yeppp! performance library. All optimized kernels in Yeppp! are implemented in NervaPy (uses old version of NervaPy with deprecated syntax).

Peer-Reviewed Publications

  • Marat Dukhan “NervaPy: A Python Framework for Developing High-Performance Assembly Kernels”, Python for High-Performance Computing (PyHPC) 2013 (slides, paper, code uses deprecated syntax)

  • Marat Dukhan “NervaPy meets Opcodes: Direct Machine Code Generation from Python”, Python for High-Performance Computing (PyHPC) 2015 (slides, paper on ACM Digital Library).

Other Presentations

Dependencies

  • Nearly all instruction classes in NervaPy are generated from Opcodes Database

  • Instruction encodings in NervaPy are validated against binutils using auto-generated tests

  • NervaPy uses six and enum34 packages as a compatibility layer between Python 2 and Python 3

Acknowledgements

HPC Garage logo Georgia Tech College of Computing logo

This work is a research project at the HPC Garage lab in the Georgia Institute of Technology, College of Computing, School of Computational Science and Engineering.

The work was supported in part by grants to Prof. Richard Vuduc’s research lab, The HPC Garage, from the National Science Foundation (NSF) under NSF CAREER award number 0953100; and a grant from the Defense Advanced Research Projects Agency (DARPA) Computer Science Study Group program

Any opinions, conclusions or recommendations expressed in this software and documentation are those of the authors and not necessarily reflect those of NSF or DARPA.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pynerva-0.0.6.tar.gz (943.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pynerva-0.0.6-py3-none-any.whl (380.5 kB view details)

Uploaded Python 3

File details

Details for the file pynerva-0.0.6.tar.gz.

File metadata

  • Download URL: pynerva-0.0.6.tar.gz
  • Upload date:
  • Size: 943.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pynerva-0.0.6.tar.gz
Algorithm Hash digest
SHA256 0de7743d5895b72f581ab43022e54f1f1744b190d1c00ae244ca15b8f0a8d673
MD5 b2e54d35f6ab0bad6c44784c1e29a534
BLAKE2b-256 4d90319c8c9f8fa0cff6f0e9ed0fb029f5e32ce4459c13b095c13be58f74578a

See more details on using hashes here.

File details

Details for the file pynerva-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: pynerva-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 380.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pynerva-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 13d49ff2c5c603abeec99c52e7ef6a0be499cbb90267df8f4bd200001be58adf
MD5 3a87ce904286738c889c74a53dff0e41
BLAKE2b-256 6ca2d02ff355e220dbb6382a2fd452584880c9b847ee3eaf4eeb20a19cd183a9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page