Python bindings; calling C code & performance - python

I'll keep my question short and simple.
Assume I have a python program which calls C++ code from a DLL compiled in C/C++.
-Will the speed/performance of the executing code be preserved?
Assume I have a python program ... has a binding to a C++ library (for example - GTK or Wx).
-Is the speed going to match that of the library as if it was compiled with a C++ program?
Thank you.

When Python calls into C++ code, the code it executes is the machine code generated by the C++ compiler. You will have some cost at the interface level, as you have to marshal Python types into C++ types and vice versa, but the C++ code itself will run at pretty much the same speed as if it were called from C++; any differences will be due to different locality of dynamically allocated memory due to different memory use patterns (which would cause your C++ code to run at different speeds depending on which C++ application called it as well).

Related

Are syntax errors in Python found at 'compile time' or 'runtime'? [duplicate]

From my understanding:
An interpreted language is a high-level language run and executed by an interpreter (a program which converts the high-level language to machine code and then executing) on the go; it processes the program a little at a time.
A compiled language is a high-level language whose code is first converted to machine-code by a compiler (a program which converts the high-level language to machine code) and then executed by an executor (another program for running the code).
Correct me if my definitions are wrong.
Now coming back to Python, I am bit confused about this. Everywhere you learn that Python is an interpreted language, but it's interpreted to some intermediate code (like byte-code or IL) and not to the machine code. So which program then executes the IM code? Please help me understand how a Python script is handled and run.
First off, interpreted/compiled is not a property of the language but a property of the implementation. For most languages, most if not all implementations fall in one category, so one might save a few words saying the language is interpreted/compiled too, but it's still an important distinction, both because it aids understanding and because there are quite a few languages with usable implementations of both kinds (mostly in the realm of functional languages, see Haskell and ML). In addition, there are C interpreters and projects that attempt to compile a subset of Python to C or C++ code (and subsequently to machine code).
Second, compilation is not restricted to ahead-of-time compilation to native machine code. A compiler is, more generally, a program that converts a program in one programming language into a program in another programming language (arguably, you can even have a compiler with the same input and output language if significant transformations are applied). And JIT compilers compile to native machine code at runtime, which can give speed very close to or even better than ahead of time compilation (depending on the benchmark and the quality of the implementations compared).
But to stop nitpicking and answer the question you meant to ask: Practically (read: using a somewhat popular and mature implementation), Python is compiled. Not compiled to machine code ahead of time (i.e. "compiled" by the restricted and wrong, but alas common definition), "only" compiled to bytecode, but it's still compilation with at least some of the benefits. For example, the statement a = b.c() is compiled to a byte stream which, when "disassembled", looks somewhat like load 0 (b); load_str 'c'; get_attr; call_function 0; store 1 (a). This is a simplification, it's actually less readable and a bit more low-level - you can experiment with the standard library dis module and see what the real deal looks like. Interpreting this is faster than interpreting from a higher-level representation.
That bytecode is either interpreted (note that there's a difference, both in theory and in practical performance, between interpreting directly and first compiling to some intermediate representation and interpret that), as with the reference implementation (CPython), or both interpreted and compiled to optimized machine code at runtime, as with PyPy.
The CPU can only understand machine code indeed. For interpreted programs, the ultimate goal of an interpreter is to "interpret" the program code into machine code. However, usually a modern interpreted language does not interpret human code directly because it is too inefficient.
The Python interpreter first reads the human code and optimizes it to some intermediate code before interpreting it into machine code. That's why you always need another program to run a Python script, unlike in C++ where you can run the compiled executable of your code directly. For example, c:\Python27\python.exe or /usr/bin/python.
The answer depends on what implementation of python is being used. If you are using lets say CPython (The Standard implementation of python) or Jython (Targeted for integration with java programming language)it is first translated into bytecode, and depending on the implementation of python you are using, this bycode is directed to the corresponding virtual machine for interpretation. PVM (Python Virtual Machine) for CPython and JVM (Java Virtual Machine) for Jython.
But lets say you are using PyPy which is another standard CPython implementation. It would use a Just-In-Time Compiler.
Yes, it is both compiled and interpreted language. Then why we generally call it as interpreted language?
see how it is both- compiled and interpreted?
First of all I want to tell that you will like my answer more if you are from the Java world.
In the Java the source code first gets converted to the byte code through javac compiler then directed to the JVM(responsible for generating the native code for execution purpose). Now I want to show you that we call the Java as compiled language because we can see that it really compiles the source code and gives the .class file(nothing but bytecode) through:
javac Hello.java -------> produces Hello.class file
java Hello -------->Directing bytecode to JVM for execution purpose
The same thing happens with python i.e. first the source code gets converted to the bytecode through the compiler then directed to the PVM(responsible for generating the native code for execution purpose). Now I want to show you that we usually call the Python as an interpreted language because the compilation happens behind the scene
and when we run the python code through:
python Hello.py -------> directly excutes the code and we can see the output provied that code is syntactically correct
# python Hello.py it looks like it directly executes but really it first generates the bytecode that is interpreted by the interpreter to produce the native code for the execution purpose.
CPython- Takes the responsibility of both compilation and interpretation.
Look into the below lines if you need more detail:
As I mentioned that CPython compiles the source code but actual compilation happens with the help of cython then interpretation happens with the help of CPython
Now let's talk a little bit about the role of Just-In-Time compiler in Java and Python
In JVM the Java Interpreter exists which interprets the bytecode line by line to get the native machine code for execution purpose but when Java bytecode is executed by an interpreter, the execution will always be slower. So what is the solution? the solution is Just-In-Time compiler which produces the native code which can be executed much more quickly than that could be interpreted. Some JVM vendors use Java Interpreter and some use Just-In-Time compiler. Reference: click here
In python to get around the interpreter to achieve the fast execution use another python implementation(PyPy) instead of CPython.
click here for other implementation of python including PyPy.
According to the official Python site, it's interpreted.
https://www.python.org/doc/essays/blurb/
Python is an interpreted, object-oriented, high-level programming language...
...
Since there is no compilation step ...
...
The Python interpreter and the extensive standard library are available...
...
Instead, when the interpreter discovers an error, it raises an
exception. When the program doesn't catch the exception, the
interpreter prints a stack trace.
Its a big confusion for people who just started working in python and the answers here are a little difficult to comprehend so i'll make it easier.
When we instruct Python to run our script, there are a few steps that Python carries out before our code actually starts crunching away:
It is compiled to bytecode.
Then it is routed to virtual machine.
When we execute some source code, Python compiles it into byte code. Compilation is a translation step, and the byte code is a low-level platform-independent representation of source code.
Note that the Python byte code is not binary machine code (e.g., instructions for an Intel chip).
Actually, Python translate each statement of the source code into byte code instructions by decomposing them into individual steps. The byte code translation is performed to speed execution.
Byte code can be run much more quickly than the original source code statements. It has.pyc extension and it will be written if it can write to our machine.
So, next time we run the same program, Python will load the .pyc file and skip the compilation step unless it's been changed. Python automatically checks the timestamps of source and byte code files to know when it must recompile. If we resave the source code, byte code is automatically created again the next time the program is run.
If Python cannot write the byte code files to our machine, our program still works. The byte code is generated in memory and simply discarded on program exit. But because .pyc files speed startup time, we may want to make sure it has been written for larger programs.
Let's summarize what happens behind the scenes.
When Python executes a program, Python reads the .py into memory, and parses it in order to get a bytecode, then goes on to execute. For each module that is imported by the program, Python first checks to see whether there is a precompiled bytecode version, in a .pyo or .pyc, that has a timestamp which corresponds to its .py file. Python uses the bytecode version if any. Otherwise, it parses the module's .py file, saves it into a .pyc file, and uses the bytecode it just created.
Byte code files are also one way of shipping Python codes. Python will still run a program if all it can find are.pyc files, even if the original .py source files are not there.
Python Virtual Machine (PVM)
Once our program has been compiled into byte code, it is shipped off for execution to Python Virtual Machine (PVM). The PVM is not a separate program. It need not be installed by itself. Actually, the PVM is just a big loop that iterates through our byte code instruction, one by one, to carry out their operations. The PVM is the runtime engine of Python. It's always present as part of the Python system. It's the component that truly runs our scripts. Technically it's just the last step of what is called the Python interpreter.
If ( You know Java ) {
Python code is converted into bytecode like java does.
That bytecode is executed again everytime you try to access it.
} else {
Python code is initially traslated into something called bytecode that is quite
close to machine language but not actual machine code
so each time we access or run it that bytecode is executed again
}
It really depends on the implementation of the language being used! There is a common step in any implementation, though: your code is first compiled (translated) to intermediate code - something between your code and machine (binary) code - called bytecode (stored into .pyc files). Note that this is a one-time step that will not be repeated unless you modify your code.
And that bytecode is executed every time you are running the program. How? Well, when we run the program, this bytecode (inside a .pyc file) is passed as input to a Virtual Machine (VM)1 - the runtime engine allowing our programs to be executed - that executes it.
Depending on the language implementation, the VM will either interpret the bytecode (in the case of CPython2 implementation) or JIT-compile3 it (in the case of PyPy4 implementation).
Notes:
1 an emulation of a computer system
2 a bytecode interpreter; the reference implementation of the language, written in C and Python - most widely used
3 compilation that is being done during the execution of a program (at runtime)
4 a bytecode JIT compiler; an alternative implementation to CPython, written in RPython (Restricted Python) - often runs faster than CPython
Almost, we can say Python is interpreted language. But we are using some part of one time compilation process in python to convert complete source code into byte-code like java language.
For newbies
Python automatically compiles your script to compiled code, so called byte code, before running it.
Running a script is not considered an import and no .pyc will be created.
For example, if you have a script file abc.py that imports another module xyz.py, when you run abc.py, xyz.pyc will be created since xyz is imported, but no abc.pyc file will be created since abc.py isn’t being imported.
Python(the interpreter) is compiled.
Proof: It won't even compile your code if it contains syntax error.
Example 1:
print("This should print")
a = 9/0
Output:
This should print
Traceback (most recent call last):
File "p.py", line 2, in <module>
a = 9/0
ZeroDivisionError: integer division or modulo by zero
Code gets compiled successfully. First line gets executed (print) second line throws ZeroDivisionError (run time error) .
Example 2:
print("This should not print")
/0
Output:
File "p.py", line 2
/0
^
SyntaxError: invalid syntax
Conclusion: If your code file contains SyntaxError nothing will execute as compilation fails.
As sone one already said, "interpreted/compiled is not a property of the language but a property of the implementation." Python can be used in interpretation mode as well as compilation mode. When you run python code directly from terminal or cmd then the python interpreter starts. Now if you write any command then this command will be directly interpreted. If you use a file containing Python code and running it in IDE or using a command prompt it will be compiled first the whole code will be converted to byte code and then it will run. So it depends on how we use it.
The python code you write is compiled into python bytecode, which creates file with extension .pyc. If compiles, again question is, why not compiled language.
Note that this isn't compilation in the traditional sense of the word. Typically, we’d say that compilation is taking a high-level language and converting it to machine code. But it is a compilation of sorts. Compiled in to intermediate code not into machine code (Hope you got it Now).
Back to the execution process, your bytecode, present in pyc file, created in compilation step, is then executed by appropriate virtual machines, in our case, the CPython VM
The time-stamp (called as magic number) is used to validate whether .py file is changed or not, depending on that new pyc file is created. If pyc is of current code then it simply skips compilation step.
Seems to be a case of semantics. I think most of us infer that the usual result of compiling is machine-code. With that in mind I say to myself that python is not compiled. I would be wrong though because compile really means convert to a lower level so converting from source to byte-code is also compiling.
In my opinion Python is put into an interpreter categoty because its designed to be capable of fully processing ( from python code to execution in cpu) individual python statement. I.e. you write one statement and you can execute it and if no errors then get the corresponding result.
Having an intermediate code (like bytecode) i believe doesnt make difference to categorize it overall as compiler. Though this component (intermediate code generation) is typically been part of compiler but it can also be used in interpreters. See wiki definition of interpreter https://en.m.wikipedia.org/wiki/Interpreter_(computing). Its a crucial piece to add efficiency in terms of execution speed. With cache its even more powerful so that if you havent changed code in current program scope you skip heavy processing steps like lexical, semantic analysis and even some of code optimization.

Does WebAssembly run faster if written in C as opposed to Python?

There's a long list of languages that can be compiled into Wasm. Is there any performance gain from writing in something like C or Rust over Python? Or is it all the same since it is being compiled to Wasm?
Short answer: Yes, because Python, the language itself, is not compiled to Wasm, but its interpreter.
Saying Python supports Wasm does not always means the same. Firstly, Python is NOT a compiled language, it's a script language. Don't expect a script language will be compiled to a native (or Wasm) language because it is not meant to work that way.
Then how Python supports Wasm? Python interpreters/runtimes like cpython, which is written in C, are compiled to Wasm. There are two popular Python runtimes that supports Python: pyodide and Wasm port for micropython (there are a lot of efforts to run Python in a browser besides the two). Both of them are interpreters that translate Python to their own bytecode and then execute bytecode in Wasm. Of course there will be huge performance penalties just like cpython in the native environment.
Compiling to WebAssembly is basically just simulating a special form of assembly targeting virtual hardware. When you read "can compile language X" into Wasm, it doesn't always mean the language literally compiles directly to Wasm. In the case of Python, to my knowledge, it means "they compiled Python interpreters to Wasm" (e.g. CPython, PyPy), so the whole Python interpreter is Wasm, but it still interprets Python source code files normally, it doesn't convert them to special Wasm modules or anything. Which means all the overhead of the Python interpreter is there, on top of the overhead of the Wasm engine, etc.
So yes, C and Rust (which can target Wasm directly by swapping out the compiler backend) will still run faster than Python code targeting CPython compiled to Wasm, for the same reasons. Tools that speed up Python when run natively (e.g. Cython, raw CPython C extensions, etc.) may also work in Wasm to get the same speed ups, but it's not a free "Compile slow interpreted language to Wasm and become fast compiled language"; computers aren't that smart yet.

Threading a c++ program in python

I have a Python application written in Kivy that uses a C++ program for a high speed calculation, then it returns a value and my Python application uses that.
The C++ program is wrapped in PyBind11 and imported into the application and then called from Python.
My issue is when the C++ program is executed, my application stops for a short while and I'd still like things to be going on in the background.
I naively thought this could be solved by threading the C++ call, but on second thoughts I think the issue lies in the GIL. Must I unlock the GIL and how could I achieve this?
Without seeing any code, I can only deduce that your Python code is waiting for the C++ code to complete before doing anything else. Which can mean either or both of the following:
you are not unlocking the GIL in the C++ code
According to Global Interpreter Lock (GIL) — Miscellaneous — pybind11 2.2.3 documentation, with pybind, this is supposed to be done like this:
py::gil_scoped_release release;
long_running_method();
py::gil_scoped_acquire acquire;
Note that you need the GIL to access any Python machinery (including returning the result). So before releasing it, make sure to convert all the data you need from Python types to C++ types.
you don't have any other active Python threads, so there's no other Python activity programmed in to do anything while the C++ call is in progress

When using the Python Interpreter, is the compiler used at all?

In Google's Python Class it reads
Python is a dynamic, interpreted (bytecode-compiled) language
I know what an interpreter is and know what bytecode is but the two together seem not to fit. After doing some reading it became a bit clearer that basically Python source code is automatically compiled before it is interpreted; but some new questions emerged.
When using the Python Interpreter does no compilation happen? If it does, when? For example if you're just typing code at the command line and it gets run each time you hit enter, when does a compiler have the opportunity to do its work?
Also in the linked to question above, #delnan gives a pretty broad definition of a compiler
A compiler is, more generally, a program that converts a program in
one programming language into a program in another programming
language...JIT compilers compile to native machine code at runtime
I guess my question is: what's the difference between an interpreter and automatic compiler? To refine the question a bit, if Python is compiled, why not compile all the way to machine code (or assembly, since I know writing compilers that can produce pure machine code is difficult)?
Perhaps it is best to forget semantics and just try to learn what Cpython is actually doing. When you invoke the Cpython binary, it does a number of things. Generally speaking, you can expect it to translate the code you've written into a sequence of bytecode instructions. This is the "compiling" stage that people will sometimes reference for python code. These are a more compact and efficient way to tell the interpreter what to do than your hand-written code. Frequently, python will cache these files for reuse in .pyc files (only re-generating if the associated .py file is newer). You can think of python bytecode as the set of instructions that the python virtual machine can run -- In a lot of ways, it's not really all that different than what you get for Java. When people speak of compiled languages (e.g. C), the compiler's job is to translate your code into a set of instructions that will run directly on your computer's hardware. Languages like Cpython and Java have an extra level of indirection (e.g. the Virtual Machine). The Virtual Machine runs directly on the computer's hardware and is responsible for interpreting the domain specific language.
Compared to standard "compiled" languages (e.g. C, Fortran), this stage is really light-weight -- and python doesn't do a lot of the checking that "traditional" compilers will do (e.g. typechecking). It pretty much only checks the syntax and does a few very simple optimizations using the peephole optimizer.

Use Cython as Python to C Converter

I have huge Python modules(+8000 lines) .They basically have tons of functions for interacting with a hardware platform via serial port by reading and writing to hardware registers.
They are not numerical algorithms. So application is just reading/writing to hardware registers/memory. I use these libraries to write custom scripts. Eventually, I need to move all these stuff to be run in an embedded processor on my hardware to have finer control, then I just kick off the event from PC and the rest is in hardware.
So I need to convert them to C.If I can have my scripts be converted to C by an automatic tool, that would save me a huge time. This is why I got attracted to Cython. Efficiency is not important my codes are not number crunchers. But generated code should be relatively small to fit in my limited memory (few hundreds of Kilobytes).
Can I use Cython as converter for my custom Python scripts to C? My guess is yes, in which case can I use these .c files to be run in my hardware? My guess is not since I have to have Cython in my hardware as well for them to run. But if just creates some .c files, I can go through and make it standalone since code is not using much of features of Python it just use it as a fast to implement script.
Yes, at its core this is what Cython does. But ...
You don't need Cython, however, you do need libpython. You may feel like it doesn't use that many Python features, but I think if you try this you'll find it's not true -- you won't be able to separate your program from its dependence on libpython while still using the Python language.
Another option is PyPy, specifically it's translation toolchain, NOT the PyPy Python interpreter. It lets you translate RPython, a subset of the Python language, into C. If you really aren't using many Python language features or libraries, this may work.
PyPy is mostly known as an alternative Python implementation, but it is also a set of tools for compiling dynamic languages into various forms. This is what allows the PyPy implementation of Python, written in (R)Python, to be compiled to machine code.
If C++ is available, Nuitka is a Python to C++ compiler that works for regular Python, not just RPython (which is what shedskin and PyPy use).
If C++ is available for that embedded platform, there is shed skin, it converts python into c++.

Categories

Resources