:mod:`heat.testing.basic_test` ============================== .. py:module:: heat.testing.basic_test .. autoapi-nested-parse:: Module for TestCases used for heat Module Contents --------------- .. py:class:: TestCase(methodName='runTest') Bases: :class:`unittest.TestCase` Helper functions for unit tests .. attribute:: __comm .. attribute:: device :annotation: :heat.core.Device .. attribute:: _hostnames :annotation: :Optional[list[str]] = None .. attribute:: other_device :annotation: :Optional[heat.core.Device] = None .. attribute:: envar :annotation: :Optional[str] = None .. role:: raw-html(raw) :format: html .. method:: setUp() -> None Sets initial RNG seed for testing .. method:: setUpClass() -> None Read the environment variable 'HEAT_TEST_USE_DEVICE' and return the requested devices. Supported values - cpu: Use CPU only (default) - gpu: Use GPU only :raises RuntimeError if value of 'HEAT_TEST_USE_DEVICE' is not recognized: .. method:: get_rank() -> Optional[int] Returns the MPI rank .. method:: get_size() -> Optional[int] Returns the MPI size .. method:: get_hostnames() -> list[str] Returns the name of the host machine(s). .. method:: assert_array_equal(heat_array: heat.DNDarray, expected_array: Union[numpy.ndarray, torch.Tensor], rtol: float = 1e-05, atol: float = 1e-08) -> None Check if the heat_array is equivalent to the expected_array. Therefore first the split heat_array is compared to the corresponding expected_array slice locally and second the heat_array is combined and fully compared with the expected_array. Note if the heat array is split it also needs to be balanced. :param heat_array: The heat array which should be checked. :type heat_array: heat.DNDarray :param expected_array: The array against which the heat_array should be checked. :type expected_array: numpy.ndarray or torch.Tensor :param rtol: The relative tolerance parameter. :type rtol: float :param atol: The absolute tolerance parameter. :type atol: float :raises AssertionError if the arrays do not equal.: .. rubric:: Examples >>> import numpy as np >>> import heat as ht >>> a = ht.ones((5, 5), split=1, dtype=ht.int32) >>> b = np.ones((5, 5), dtype=np.int32) >>> self.assert_array_equal(a, b) >>> c = np.ones((5, 5), dtype=np.int64) >>> self.assert_array_equal(a, c) AssertionError: [...] >>> c = np.zeros((5, 5), dtype=np.int32) >>> self.assert_array_equal(a, c) AssertionError: [...] .. method:: assert_func_equal(shape: Union[tuple[Any, Ellipsis], list[Any]], heat_func: Callable[Ellipsis, Any], numpy_func: Callable[Ellipsis, Any], distributed_result: bool = True, heat_args: Optional[dict[str, Any]] = None, numpy_args: Optional[dict[str, Any]] = None, data_types: tuple[type, Ellipsis] = (np.int32, np.int64, np.float32, np.float64), low: int = -10000, high: int = 10000) -> None Creates random tensors of the given shape with different data types. All of these tensors will be tested with `ht.assert_func_equal_for_tensor`. :param shape: The shape of which a random tensors will be created and tested against :type shape: tuple or list :param heat_func: The function that is to be tested :type heat_func: function :param numpy_func: The numpy implementation of an equivalent function to test against :type numpy_func: function :param heat_args: The keyword arguments that will be passed to the heat function. Array and split function don't need to be specified. Default is {}. :type heat_args: dictionary, optional :param numpy_args: The keyword arguments that will be passed to the numpy function. Array doesn't need to be specified. Default is {}. :type numpy_args: dictionary, optional :param distributed_result: Specify whether the result of the heat function is distributed across all nodes or all nodes have the full result. Default is True. :type distributed_result: bool, optional :param data_types: Tensors with all of these dtypes will be created and tested. Each type must to be a numpy dtype. Default is [numpy.int32, numpy.int64, numpy.float32, numpy.float64] :type data_types: list of numpy dtypes, optional :param low: In case one of the data_types has integer types, this is the lower bound for the random values. Default is -10000 :type low: int, optional :param high: In case one of the data_types has integer types, this is the upper bound for the random values. Default is 10000 :type high: int, optional :raises AssertionError if the functions do not perform equally.: .. rubric:: Examples >>> import numpy as np >>> import heat as ht >>> self.assert_func_equal((2, 2), ht.exp, np.exp) >>> self.assert_func_equal((2, 2), ht.exp, np.log) AssertionError: [...] >>> self.assert_func_equal((1, 3, 5), ht.any, np.any, distributed_result=False) >>> heat_args = {"sorted": True, "axis": 0} >>> numpy_args = {"axis": 0} >>> self.assert_func_equal( ... [5, 5, 5, 5], ht.unique, np.unique, heat_arg=heat_args, numpy_args=numpy_args ... ) .. method:: assert_func_equal_for_tensor(tensor: Union[numpy.ndarray, torch.Tensor], heat_func: Callable[Ellipsis, Any], numpy_func: Callable[Ellipsis, Any], heat_args: Optional[dict[str, Any]] = None, numpy_args: Optional[dict[str, Any]] = None, distributed_result: bool = True) -> None Tests if the heat function and the numpy function create the equal result on the given tensor. :param tensor: The tensor on which the heat function will be executed. :type tensor: torch.Tensor or numpy.ndarray :param heat_func: The function that is to be tested :type heat_func: function :param numpy_func: The numpy implementation of an equivalent function to test against :type numpy_func: function :param heat_args: The keyword arguments that will be passed to the heat function. Array and split function don't need to be specified. Default is {}. :type heat_args: dictionary, optional :param numpy_args: The keyword arguments that will be passed to the numpy function. Array doesn't need to be specified. Default is {}. :type numpy_args: dictionary, optional :param distributed_result: Specify whether the result of the heat function is distributed across all nodes or all nodes have the full result. Default is True. :type distributed_result: bool, optional :raises AssertionError if the functions to not perform equally.: .. rubric:: Examples >>> import numpy as np >>> import heat as ht >>> a = np.arange(10) >>> self.assert_func_equal_for_tensor(a, ht.exp, np.exp) >>> self.assert_func_equal_for_tensor(a, ht.exp, np.log) AssertionError: [...] >>> self.assert_func_equal_for_tensor(a, ht.any, np.any, distributed_result=False) >>> a = torch.ones([5, 5, 5, 5]) >>> heat_args = {"sorted": True, "axis": 0} >>> numpy_args = {"axis": 0} >>> self.assert_func_equal_for_tensor( ... a, ht.unique, np.unique, heat_arg=heat_args, numpy_args=numpy_args ... ) .. method:: assertTrue_memory_layout(tensor: heat.DNDarray, order: str) -> None Checks that the memory layout of a given heat tensor is as specified by argument order. :param tensor: The input array. :type tensor: DNDarray :param order: 'C' for C-like (row-major), 'F' for Fortran-like (column-major) memory layout. :type order: str .. method:: __create_random_np_array(shape: Union[list[Any], tuple[Any]], dtype: type = np.float32, low: int = -10000, high: int = 10000) -> numpy.ndarray Creates a random array based on the input parameters. The used seed will be printed to stdout for debugging purposes. :param shape: The shape of the random array to be created. :type shape: list or tuple :param dtype: The datatype of the resulting array. If dtype is subclass of np.floating then numpy.random.randn is used to create random values. If dtype is subclass of np.integer then numpy.random.randint is called with the low and high argument to create the random values. Default is numpy.float64 :type dtype: np.dtype, optional :param low: In case dtype is an integer type, this is the lower bound for the random values. Default is -10000 :type low: int, optional :param high: In case dtype is an integer type, this is the upper bound for the random values. Default is 10000 :type high: int, optional :returns: **res** -- An array of random values with the specified shape and dtype. :rtype: numpy.ndarray :raises ValueError if the dtype is not a subtype of numpy.integer or numpy.floating: .. method:: get_tmpdir() Create a temporary directory in the current working directory. When running with multiple tasks, only rank 0 creates and destroys the directory, but the path is communicated across all ranks. The directory is cleaned up / deleted when the variable tmpdir is garbage collected on rank 0. :returns: * **path** (*str*) -- Path to the temporary directory * **tmpdir** (*object or None*) -- On rank 0: A Python object administering the temporary directory, on other ranks, None.