Replies: 11 comments 61 replies
-
What is the difference between this |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
All your examples seem to be about testing. Why do you need the tests to be translated? |
Beta Was this translation helpful? Give feedback.
-
def sympy(f):
def wrap(x):
expr = f(x)
return expr.subs(Symbol('x'), x)
return wrap
`` This implementation requires:
Why not implement the decorator like: import sympy as sp
import inspect
def sympy(f):
sig = inspect.signature(f)
args = [sp.Symbol(a) for a in sig.parameters]
return sp.lambdify(args, f(*args)) with the function defined as: @sympy
def f(x : float):
from sympy import tan
return tan(x).diff() ? |
Beta Was this translation helpful? Give feedback.
-
Another use case is to store the results of the factorial functions in an array and use the result in another function to improve performance. import numpy as np
# Function to compute factorial
def factorial(n):
return 1 if n <= 1 else n * factorial(n - 1)
# Function to compute binomial coefficient (n choose k)
def binomial_coefficient(n, k):
if n<20:
fact_n = fact_array[n]
else:
fact_n = factorial(n)
if n<20:
fact_k = fact_array[k]
else:
fact_k = factorial(k)
if n-k<20:
fact_nk = fact_array[n-k]
else:
fact_nk = factorial(n-k)
# Compute binomial coefficient using the computed factorials
return fact_n // (fact_k * fact_nk)
@precompute
def compute_first_n_factorials(n):
from functools import lru_cache
fact = lru_cache(factorial)
return np.array([fact(i) for i in range(n)])
n:'Final' = 20
fact_array = compute_first_n_factorials(n)
if __name__ == "__main__":
n = 10
k = 3
binomial_coeff = binomial_coefficient(n, k)
print(f"Binomial coefficient C({n}, {k}) is: {binomial_coeff}")
`` |
Beta Was this translation helpful? Give feedback.
-
Summary of related decorators:
|
Beta Was this translation helpful? Give feedback.
-
Another Example in the domain of finite elements. # Function to read node and element information from a mesh file
@precompute
def read_mesh(filename):
...
return nodes, elements
# Function that performs Finite Element Analysis using node and element data
def perform_fea(parameters):
# Read node and element information from the mesh file
filename: 'Final' = 'mesh_data.txt' # Provide the filename of the mesh data file
nodes, elements = read_mesh(filename)
# Perform FEA calculations using the provided node and element data
print("Performing Finite Element Analysis...")
# Placeholder for actual FEA calculations
# Access nodes and elements to perform calculations
if __name__ == '__main__':
# Perform Finite Element Analysis
parameters = ...
perform_fea(parameters)
`` |
Beta Was this translation helpful? Give feedback.
-
I am checking the old tests to make sure I have fully understood. I see this: pyccel/tests/symbolic/scripts/decorator.py Lines 21 to 36 in b39fe9a You have 1 function with 1 argument which matches my description above, but also a second function |
Beta Was this translation helpful? Give feedback.
-
For me, it seems that the behavior of the |
Beta Was this translation helpful? Give feedback.
-
Another use case where we can extract the length of the SIMD vector using a Python function that calculates it depending on the architecture. @precompute
def get_simd_length():
# compute the simd length specific to the architecture
import platform
def calculate_simd_vector_total_size(architecture):
if 'x86' in architecture:
# Assuming AVX architecture
vector_register_size_bits = 256
elif 'arm' in architecture:
# Assuming ARM NEON architecture
vector_register_size_bits = 128
else:
raise ValueError("Unsupported architecture")
return vector_register_size_bits
# Detect architecture
architecture = platform.machine()
# Calculate total size of SIMD vector
total_size_bits = calculate_simd_vector_total_size(architecture)
return total_size_bits//64
def performe_computation(y:'float[:]')
simd_lenght:'Final' = get_simd_lenght()
x:'Final' = np.empty(simd_length)
for i in range(y.shape[0]//simd_length):
x[:] = y[i*simd_lenght:(i+1*simd_length)]
#$ omp simd
for j in range(simd_length):
... |
Beta Was this translation helpful? Give feedback.
-
Another example is to check if a library exists and use it otherwise refer to manual implementation @precompute
def check_blas():
"""
Checks if BLAS is available.
Returns:
bool: True if BLAS is available, False otherwise.
"""
try:
import scipy.linalg.blas
return True
except ImportError:
return False
def _blas_matrix_vector_product(A, x):
from scipy.linalg.blas import dtrmv
return dtrmv(A, x)
def _manual_matrix_vector_product(A, x):
"""
Performs matrix-vector product Ax using manual implementation.
Parameters:
A (ndarray): Matrix of shape (m, n).
x (ndarray): Vector of shape (n,).
Returns:
ndarray: Resulting vector of shape (m,).
"""
...
def matrix_vector_product(A, x):
"""
Performs matrix-vector product Ax using BLAS if available; otherwise, uses manual implementation.
Parameters:
A (ndarray): Matrix of shape (m, n).
x (ndarray): Vector of shape (n,).
Returns:
ndarray: Resulting vector of shape (m,).
"""
if check_blas():
return _blas_matrix_vector_product(A, x)
else:
return _manual_matrix_vector_product(A, x)
``` |
Beta Was this translation helpful? Give feedback.
-
Previously, the
@python
decorator was utilized to signal to the compiler that a function should be executed at compile time, and its result should be directly incorporated into the code. However, this mechanism was removed in the issue #668 because it was not handled properly.I want to reintroduce this mechanism and make it more general than before as I think it can be useful in many instances, where we need to precompute some expressions and hardcode them directly in the code to make the code faster.
Additionally, it can be used in unit testing and generate an executable that does everything instead of separating the implementation from the unit testing.
Key Features:
@precompute
decorator should be able to call other functions in the same file or access the imported files. previously the function with the@python
didn't have access to other functions in the same file.@precompute
decorator should be declared asFinal
, to ensure immutability.precompute
decorator can only be called using literals and constant arrays, we can also handle arguments that are declaredFinal
because we can extract their value.Here I constructed many examples to illustrate its usefulness.
precompute
decorator to generate test cases:Beta Was this translation helpful? Give feedback.
All reactions