Skip to content
Snippets Groups Projects

Various extensions to the vectorizer

Merged Daniel Bauer requested to merge hyteg/pystencils:bauerd/vec-extensions into v2.0-dev
Viewing commit 8b8d5534
Show latest version
2 files
+ 77
21
Preferences
Compare changes
Files
2
import sympy as sp
import numpy as np
import pytest
from dataclasses import replace
from pystencils import fields, create_kernel, CreateKernelConfig, Target, Assignment, Field
from pystencils.backend.ast import dfs_preorder
@@ -34,7 +35,6 @@ def binary_function(name, xp):
}[name]
@pytest.mark.parametrize("target", (Target.GenericCPU, Target.CUDA))
@pytest.mark.parametrize(
"function_name",
(
@@ -54,17 +54,13 @@ def binary_function(name, xp):
),
)
@pytest.mark.parametrize("dtype", (np.float32, np.float64))
def test_unary_functions(target, function_name, dtype):
if target == Target.CUDA:
xp = pytest.importorskip("cupy")
else:
xp = np
def test_unary_functions(gen_config, xp, function_name, dtype):
sp_func, xp_func = unary_function(function_name, xp)
resolution = np.finfo(dtype).resolution
# Array size should be larger than eight, such that vectorized kernels don't just run their remainder loop
inp = xp.array(
[[0.1, 0.2, 0.3], [-0.8, -1.6, -12.592], [xp.pi, xp.e, 0.0]], dtype=dtype
[0.1, 0.2, 0.0, -0.8, -1.6, -12.592, xp.pi, xp.e, -0.3], dtype=dtype
)
outp = xp.zeros_like(inp)
@@ -74,7 +70,7 @@ def test_unary_functions(target, function_name, dtype):
outp_field = inp_field.new_field_with_different_name("outp")
asms = [Assignment(outp_field.center(), sp_func(inp_field.center()))]
gen_config = CreateKernelConfig(target=target, default_dtype=dtype)
gen_config = replace(gen_config, default_dtype=dtype)
kernel = create_kernel(asms, gen_config)
kfunc = kernel.compile()
@@ -83,28 +79,22 @@ def test_unary_functions(target, function_name, dtype):
xp.testing.assert_allclose(outp, reference, rtol=resolution)
@pytest.mark.parametrize("target", (Target.GenericCPU, Target.CUDA))
@pytest.mark.parametrize("function_name", ("min", "max", "pow", "atan2"))
@pytest.mark.parametrize("dtype", (np.float32, np.float64))
def test_binary_functions(target, function_name, dtype):
if target == Target.CUDA:
xp = pytest.importorskip("cupy")
else:
xp = np
sp_func, np_func = binary_function(function_name, xp)
def test_binary_functions(gen_config, xp, function_name, dtype):
sp_func, xp_func = binary_function(function_name, xp)
resolution: dtype = np.finfo(dtype).resolution
inp = xp.array(
[[0.1, 0.2, 0.3], [-0.8, -1.6, -12.592], [xp.pi, xp.e, 0.0]], dtype=dtype
[0.1, 0.2, 0.3, -0.8, -1.6, -12.592, xp.pi, xp.e, 0.0], dtype=dtype
)
inp2 = xp.array(
[[3.1, -0.5, 21.409], [11.0, 1.0, -14e3], [2.0 * xp.pi, -xp.e, 0.0]],
[3.1, -0.5, 21.409, 11.0, 1.0, -14e3, 2.0 * xp.pi, -xp.e, 0.0],
dtype=dtype,
)
outp = xp.zeros_like(inp)
reference = np_func(inp, inp2)
reference = xp_func(inp, inp2)
inp_field = Field.create_from_numpy_array("inp", inp)
inp2_field = Field.create_from_numpy_array("inp2", inp)
@@ -115,7 +105,7 @@ def test_binary_functions(target, function_name, dtype):
outp_field.center(), sp_func(inp_field.center(), inp2_field.center())
)
]
gen_config = CreateKernelConfig(target=target, default_dtype=dtype)
gen_config = replace(gen_config, default_dtype=dtype)
kernel = create_kernel(asms, gen_config)
kfunc = kernel.compile()
@@ -124,6 +114,69 @@ def test_binary_functions(target, function_name, dtype):
xp.testing.assert_allclose(outp, reference, rtol=resolution)
@pytest.mark.parametrize("dtype", [np.int32, np.int64])
def test_integer_abs(gen_config, xp, dtype):
sp_func, xp_func = unary_function('abs', xp)
smallest = np.iinfo(dtype).min
largest = np.iinfo(dtype).max
inp = xp.array([
-1, 0, 1, 3, -5, -312, smallest + 1, largest
], dtype=dtype)
outp = xp.zeros_like(inp)
reference = xp_func(inp)
inp_field = Field.create_from_numpy_array("inp", inp)
outp_field = inp_field.new_field_with_different_name("outp")
asms = [Assignment(outp_field.center(), sp_func(inp_field.center()))]
gen_config = replace(gen_config, default_dtype=dtype)
kernel = create_kernel(asms, gen_config)
kfunc = kernel.compile()
kfunc(inp=inp, outp=outp)
xp.testing.assert_array_equal(outp, reference)
@pytest.mark.parametrize("function_name", ("min", "max"))
@pytest.mark.parametrize("dtype", [np.int32, np.int64])
def test_integer_binary_functions(gen_config, xp, function_name, dtype):
sp_func, xp_func = binary_function(function_name, xp)
smallest = np.iinfo(dtype).min
largest = np.iinfo(dtype).max
inp1 = xp.array([
-1, 0, 1, 3, -5, -312, smallest + 1, largest
], dtype=dtype)
inp2 = xp.array([
3, -5, 1, 12, 1, 11, smallest + 42, largest - 3
], dtype=dtype)
outp = xp.zeros_like(inp1)
reference = xp_func(inp1, inp2)
inp_field = Field.create_from_numpy_array("inp1", inp1)
inp2_field = Field.create_from_numpy_array("inp2", inp2)
outp_field = inp_field.new_field_with_different_name("outp")
asms = [
Assignment(
outp_field.center(), sp_func(inp_field.center(), inp2_field.center())
)
]
gen_config = replace(gen_config, default_dtype=dtype)
kernel = create_kernel(asms, gen_config)
kfunc = kernel.compile()
kfunc(inp1=inp1, inp2=inp2, outp=outp)
xp.testing.assert_array_equal(outp, reference)
@pytest.mark.parametrize('a', [sp.Symbol('a'), fields('a: float64[2d]').center])
def test_avoid_pow(a):
x = fields('x: float64[2d]')