@@ -897,6 +897,7 @@ def fast_eval( # noqa: C901
897
897
The output array.
898
898
"""
899
899
out = kwargs .pop ("_output" , None )
900
+ optimization = kwargs .pop ("_optimization" , "aggressive" )
900
901
dtype = kwargs .pop ("dtype" , None )
901
902
where : dict | None = kwargs .pop ("_where_args" , None )
902
903
if isinstance (out , blosc2 .NDArray ):
@@ -962,12 +963,12 @@ def fast_eval( # noqa: C901
962
963
expression (tuple (chunk_operands .values ()), result , offset = offset )
963
964
else :
964
965
if where is None :
965
- result = ne .evaluate (expression , chunk_operands )
966
+ result = ne .evaluate (expression , chunk_operands , optimization = optimization )
966
967
else :
967
968
# Apply the where condition (in result)
968
969
if len (where ) == 2 :
969
970
new_expr = f"where({ expression } , _where_x, _where_y)"
970
- result = ne .evaluate (new_expr , chunk_operands )
971
+ result = ne .evaluate (new_expr , chunk_operands , optimization = optimization )
971
972
else :
972
973
# We do not support one or zero operands in the fast path yet
973
974
raise ValueError ("Fast path: the where condition must be a tuple with two elements" )
@@ -1068,6 +1069,7 @@ def slices_eval( # noqa: C901
1068
1069
The output array.
1069
1070
"""
1070
1071
out : blosc2 .NDArray | None = kwargs .pop ("_output" , None )
1072
+ optimization = kwargs .pop ("_optimization" , "aggressive" )
1071
1073
chunks = kwargs .get ("chunks" )
1072
1074
where : dict | None = kwargs .pop ("_where_args" , None )
1073
1075
_indices = kwargs .pop ("_indices" , False )
@@ -1186,7 +1188,7 @@ def slices_eval( # noqa: C901
1186
1188
continue
1187
1189
1188
1190
if where is None :
1189
- result = ne .evaluate (expression , chunk_operands )
1191
+ result = ne .evaluate (expression , chunk_operands , optimization = optimization )
1190
1192
else :
1191
1193
# Apply the where condition (in result)
1192
1194
if len (where ) == 2 :
@@ -1195,9 +1197,9 @@ def slices_eval( # noqa: C901
1195
1197
# result = np.where(result, x, y)
1196
1198
# numexpr is a bit faster than np.where, and we can fuse operations in this case
1197
1199
new_expr = f"where({ expression } , _where_x, _where_y)"
1198
- result = ne .evaluate (new_expr , chunk_operands )
1200
+ result = ne .evaluate (new_expr , chunk_operands , optimization = optimization )
1199
1201
elif len (where ) == 1 :
1200
- result = ne .evaluate (expression , chunk_operands )
1202
+ result = ne .evaluate (expression , chunk_operands , optimization = optimization )
1201
1203
if _indices or _order :
1202
1204
# Return indices only makes sense when the where condition is a tuple with one element
1203
1205
# and result is a boolean array
@@ -1332,6 +1334,7 @@ def reduce_slices( # noqa: C901
1332
1334
The resulting output array.
1333
1335
"""
1334
1336
out = kwargs .pop ("_output" , None )
1337
+ optimization = kwargs .pop ("_optimization" , "aggressive" )
1335
1338
where : dict | None = kwargs .pop ("_where_args" , None )
1336
1339
reduce_op = reduce_args .pop ("op" )
1337
1340
axis = reduce_args ["axis" ]
@@ -1468,14 +1471,14 @@ def reduce_slices( # noqa: C901
1468
1471
# We don't have an actual expression, so avoid a copy
1469
1472
result = chunk_operands ["o0" ]
1470
1473
else :
1471
- result = ne .evaluate (expression , chunk_operands )
1474
+ result = ne .evaluate (expression , chunk_operands , optimization = optimization )
1472
1475
else :
1473
1476
# Apply the where condition (in result)
1474
1477
if len (where ) == 2 :
1475
1478
new_expr = f"where({ expression } , _where_x, _where_y)"
1476
- result = ne .evaluate (new_expr , chunk_operands )
1479
+ result = ne .evaluate (new_expr , chunk_operands , optimization = optimization )
1477
1480
elif len (where ) == 1 :
1478
- result = ne .evaluate (expression , chunk_operands )
1481
+ result = ne .evaluate (expression , chunk_operands , optimization = optimization )
1479
1482
x = chunk_operands ["_where_x" ]
1480
1483
result = x [result ]
1481
1484
else :
@@ -1579,6 +1582,8 @@ def chunked_eval( # noqa: C901
1579
1582
Default is False.
1580
1583
_output: NDArray or np.ndarray, optional
1581
1584
The output array to store the result.
1585
+ _optimization: str, optional
1586
+ The optimization level to use. Default is 'aggressive'.
1582
1587
_where_args: dict, optional
1583
1588
Additional arguments for conditional evaluation.
1584
1589
"""
@@ -2399,6 +2404,8 @@ def compute(self, item=None, **kwargs) -> blosc2.NDArray:
2399
2404
# When NumPy ufuncs are called, the user may add an `out` parameter to kwargs
2400
2405
if "out" in kwargs :
2401
2406
kwargs ["_output" ] = kwargs .pop ("out" )
2407
+ if "optimization" in kwargs :
2408
+ kwargs ["_optimization" ] = kwargs .pop ("optimization" )
2402
2409
if hasattr (self , "_output" ):
2403
2410
kwargs ["_output" ] = self ._output
2404
2411
if hasattr (self , "_where_args" ):
@@ -2538,7 +2545,7 @@ def save(self, urlpath=None, **kwargs):
2538
2545
}
2539
2546
2540
2547
@classmethod
2541
- def _new_expr (cls , expression , operands , guess , out = None , where = None ):
2548
+ def _new_expr (cls , expression , operands , guess , out = None , where = None , optimization = "aggressive" ):
2542
2549
# Validate the expression
2543
2550
validate_expr (expression )
2544
2551
if guess :
@@ -2578,6 +2585,7 @@ def _new_expr(cls, expression, operands, guess, out=None, where=None):
2578
2585
new_expr ._output = out
2579
2586
if where is not None :
2580
2587
new_expr ._where_args = where
2588
+ new_expr ._optimization = optimization
2581
2589
return new_expr
2582
2590
2583
2591
@@ -2864,6 +2872,7 @@ def lazyexpr(
2864
2872
where : tuple | list | None = None ,
2865
2873
local_dict : dict | None = None ,
2866
2874
global_dict : dict | None = None ,
2875
+ optimization : str = "aggressive" ,
2867
2876
) -> LazyExpr :
2868
2877
"""
2869
2878
Get a LazyExpr from an expression.
@@ -2889,6 +2898,10 @@ def lazyexpr(
2889
2898
global_dict: dict, optional
2890
2899
The global dictionary to use when looking for operands in the expression.
2891
2900
If not provided, the global dictionary of the caller will be used.
2901
+ optimization: str, optional
2902
+ The optimization level to use when evaluating the expression. Possible
2903
+ values are "aggressive" and "moderate". The default value is "aggressive".
2904
+ This parameter has the same meaning as in `numexpr.evaluate()`.
2892
2905
2893
2906
Returns
2894
2907
-------
@@ -2925,13 +2938,16 @@ def lazyexpr(
2925
2938
expression .operands .update (operands )
2926
2939
if out is not None :
2927
2940
expression ._output = out
2941
+ expression ._optimization = optimization
2928
2942
if where is not None :
2929
2943
where_args = {"_where_x" : where [0 ], "_where_y" : where [1 ]}
2930
2944
expression ._where_args = where_args
2931
2945
return expression
2932
2946
elif isinstance (expression , blosc2 .NDArray ):
2933
2947
operands = {"o0" : expression }
2934
- return LazyExpr ._new_expr ("o0" , operands , guess = False , out = out , where = where )
2948
+ return LazyExpr ._new_expr (
2949
+ "o0" , operands , guess = False , out = out , where = where , optimization = optimization
2950
+ )
2935
2951
2936
2952
if operands is None :
2937
2953
# Try to get operands from variables in the stack
@@ -2948,7 +2964,9 @@ def lazyexpr(
2948
2964
# _new_expr will take care of the constructor, but needs an empty dict in operands
2949
2965
operands = {}
2950
2966
2951
- return LazyExpr ._new_expr (expression , operands , guess = True , out = out , where = where )
2967
+ return LazyExpr ._new_expr (
2968
+ expression , operands , guess = True , out = out , where = where , optimization = optimization
2969
+ )
2952
2970
2953
2971
2954
2972
def _open_lazyarray (array ):
@@ -2985,7 +3003,7 @@ def _open_lazyarray(array):
2985
3003
2986
3004
2987
3005
# Mimim numexpr's evaluate function
2988
- def evaluate (ex , local_dict = None , global_dict = None ):
3006
+ def evaluate (ex , local_dict = None , global_dict = None , optimization = "aggressive" ):
2989
3007
"""
2990
3008
Evaluate a string expression using the Blosc2 compute engine.
2991
3009
@@ -3008,6 +3026,10 @@ def evaluate(ex, local_dict=None, global_dict=None):
3008
3026
global_dict: dict, optional
3009
3027
The global dictionary to use when looking for operands in the expression.
3010
3028
If not provided, the global dictionary of the caller will be used.
3029
+ optimization: str, optional
3030
+ The optimization level to use when evaluating the expression. Possible
3031
+ values are "aggressive" and "moderate". The default value is "aggressive".
3032
+ This parameter has the same meaning as in `numexpr.evaluate()`.
3011
3033
3012
3034
Returns
3013
3035
-------
@@ -3030,7 +3052,7 @@ def evaluate(ex, local_dict=None, global_dict=None):
3030
3052
[ 5.515625 8.25 11.765625]
3031
3053
[16.0625 21.140625 27. ]]
3032
3054
"""
3033
- lexpr = lazyexpr (ex , local_dict = local_dict , global_dict = global_dict )
3055
+ lexpr = lazyexpr (ex , local_dict = local_dict , global_dict = global_dict , optimization = optimization )
3034
3056
return lexpr [:]
3035
3057
3036
3058
0 commit comments