or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compiled-expressions.mdexpression-analysis.mdexpression-evaluation.mdindex.mdthreading-performance.mdvml-integration.md

compiled-expressions.mddocs/

0

# Compiled Expressions

1

2

Pre-compilation of expressions for repeated evaluation with different data, providing optimal performance for expressions used multiple times. The NumExpr class allows creating reusable expression objects that avoid repeated parsing and compilation overhead.

3

4

## Capabilities

5

6

### NumExpr Class

7

8

Creates a pre-compiled expression object that can be executed multiple times with different variable values, eliminating parsing and compilation overhead for repeated use.

9

10

```python { .api }

11

class NumExpr:

12

"""

13

Pre-compiled expression object for repeated evaluation.

14

15

This class represents a compiled mathematical expression that can be

16

executed multiple times with different input data, providing optimal

17

performance when the same expression structure is used repeatedly.

18

"""

19

20

def __init__(self, ex, signature=(), sanitize=True, **kwargs):

21

"""

22

Create a compiled expression object.

23

24

Parameters:

25

- ex (str): Mathematical expression string to compile

26

- signature (tuple): Variable signature for type checking and optimization

27

- sanitize (bool): Enable expression sanitization for security

28

- **kwargs: Additional compilation options

29

30

Raises:

31

ValueError: If expression syntax is invalid

32

"""

33

34

def run(self, *args, **kwargs):

35

"""

36

Execute the compiled expression with provided arguments.

37

38

Parameters:

39

- *args: Positional arguments corresponding to variables in signature order

40

- **kwargs: Named arguments for variable substitution

41

42

Returns:

43

ndarray: Result of expression evaluation

44

45

Raises:

46

ValueError: If argument types or shapes are incompatible

47

"""

48

49

@property

50

def signature(self):

51

"""Get the variable signature for this compiled expression."""

52

53

@property

54

def input_names(self):

55

"""Get the input variable names for this expression."""

56

```

57

58

**Usage Examples:**

59

60

```python

61

import numpy as np

62

import numexpr as ne

63

64

# Create a compiled expression

65

expr = ne.NumExpr("a * b + c")

66

67

# Execute with different data sets

68

a1, b1, c1 = np.random.random((3, 10000))

69

result1 = expr.run(a1, b1, c1)

70

71

a2, b2, c2 = np.random.random((3, 5000))

72

result2 = expr.run(a2, b2, c2)

73

74

# Using keyword arguments

75

result3 = expr.run(a=a1*2, b=b1*3, c=c1/2)

76

77

# Complex mathematical expression

78

complex_expr = ne.NumExpr("sin(x) * exp(-y/scale) + sqrt(x*y)")

79

x = np.linspace(0, 10, 1000)

80

y = np.linspace(0, 5, 1000)

81

for scale in [1, 2, 5, 10]:

82

result = complex_expr.run(x, y, scale)

83

# Process result...

84

```

85

86

87

88

## Advanced Usage Patterns

89

90

### Type-Specific Compilation

91

92

```python

93

# Specify variable types for optimized compilation

94

expr = ne.NumExpr("a * b + c", signature=(('a', 'double'), ('b', 'double'), ('c', 'double')))

95

96

# Mixed types

97

mixed_expr = ne.NumExpr("mask & (values > threshold)",

98

signature=(('mask', 'bool'), ('values', 'double'), ('threshold', 'double')))

99

```

100

101

### Memory-Efficient Patterns

102

103

```python

104

# Pre-allocate output array for repeated use

105

expr = ne.NumExpr("a * 2 + b")

106

output = np.empty(10000)

107

108

for i in range(100):

109

a = get_data_a(i) # Get new data

110

b = get_data_b(i)

111

expr.run(a, b, out=output) # Reuse output array

112

process_result(output)

113

```

114

115

### Conditional Compilation

116

117

```python

118

# Compile different expressions based on runtime conditions

119

if use_complex_math:

120

expr = ne.NumExpr("sqrt(real(z)**2 + imag(z)**2)")

121

else:

122

expr = ne.NumExpr("sqrt(a**2 + b**2)")

123

124

# Use the appropriate compiled expression

125

result = expr.run(data)

126

```

127

128

### Expression Composition

129

130

```python

131

# Build complex expressions from components

132

base_expr = "a * b"

133

if apply_transformation:

134

full_expr = f"log({base_expr} + 1)"

135

else:

136

full_expr = base_expr

137

138

compiled = ne.NumExpr(full_expr)

139

```

140

141

## Performance Considerations

142

143

### When to Use Compiled Expressions

144

145

**Ideal Cases:**

146

- Expressions evaluated many times (>10 iterations)

147

- Complex mathematical expressions with multiple operations

148

- Fixed expression structure with varying data

149

- Performance-critical loops where compilation overhead matters

150

151

**Less Beneficial:**

152

- Simple expressions evaluated once or twice

153

- Very small arrays (< 1000 elements)

154

- Expressions that change frequently

155

156

### Memory and Threading

157

158

Compiled expressions automatically:

159

- Use the current threading configuration (`get_num_threads()`)

160

- Respect VML settings for accelerated functions

161

- Apply chunking strategies for cache optimization

162

- Reuse internal memory allocations across runs

163

164

### Compilation Time vs. Execution Time

165

166

- Compilation overhead: ~0.1-1ms for typical expressions

167

- Execution speedup: 2-15x for medium to large arrays

168

- Break-even point: Usually 2-5 evaluations depending on array size and expression complexity

169

170

The `NumExpr` class is most effective when the same expression structure is used repeatedly with different data, amortizing the compilation cost across multiple evaluations.