Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: add bool type #54

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

tylerjereddy
Copy link
Contributor

  • I need a bool type for Python array API standard
    conformance, and as far as I know Kokkos doesn't work
    with such a view type under the hood?

  • if I alias bool_ and bool to the uint8 type,
    the conformance test suite can see through it, and
    resolves the alias and fails my suite

  • I'm trying another approach now, but this fails
    i.e., the local pykokkos-base testsuite with

AttributeError: module 'kokkos.libpykokkos' has no attribute 'KokkosView_bool_HostSpace_LayoutRight_1'
  • I'm not so sure either of these approaches really have many
    prospects for success--I'm open to better ideas...

[skip ci]

* I need a bool type for Python array API standard
conformance, and as far as I know Kokkos doesn't work
with such a view type under the hood?

* if I alias `bool_` and `bool` to the `uint8` type,
the conformance test suite can see through it, and
resolves the alias and fails my suite

* I'm trying another approach now, but this fails
i.e., the local `pykokkos-base` testsuite with
```
AttributeError: module 'kokkos.libpykokkos' has no attribute 'KokkosView_bool_HostSpace_LayoutRight_1'
```

* I'm not so sure either of these approaches really have many
prospects for success--I'm open to better ideas...

[skip ci]
@@ -134,6 +134,7 @@ enum KokkosViewDataType {
Uint64,
Float32,
Float64,
Bool,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't this Bool entity need to actually exist under the hood??

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not for the enum, this basically is just a definition

Comment on lines 78 to 79
typedef uint8_t bool_t;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please if you do use using bool_t = uint8_t

@@ -134,6 +134,7 @@ enum KokkosViewDataType {
Uint64,
Float32,
Float64,
Bool,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not for the enum, this basically is just a definition

@tylerjereddy
Copy link
Contributor Author

Based on feedback from Jakob, I pushed in a small change to switch back to compiling with genuine bool type (I think), which does succeed at build stage, but has a few tests not passing yet:

FAILED kokkos/test/views.py::PyKokkosBaseViewsTests::test_view_access - AssertionError: True != 2
FAILED kokkos/test/views.py::PyKokkosBaseViewsTests::test_view_create_mirror - AssertionError: True != 3
FAILED kokkos/test/views.py::PyKokkosBaseViewsTests::test_view_create_mirror_view - AssertionError: True != 3
FAILED kokkos/test/views.py::PyKokkosBaseViewsTests::test_view_deep_copy - AssertionError: True != 3
FAILED kokkos/test/views.py::PyKokkosBaseViewsTests::test_view_iadd - AssertionError: True != 4
FAILED kokkos/test/views.py::PyKokkosBaseViewsTests::test_view_imul - AssertionError: True != 3
FAILED kokkos/test/views.py::PyKokkosBaseViewsTests::test_view_isub - AssertionError: True != 7

Each of those failures look pretty similar--one example:

__________________________________________________________________________________________________________________________________________ PyKokkosBaseViewsTests.test_view_isub ___________________________________________________________________________________________________________________________________________

self = <test.views.PyKokkosBaseViewsTests testMethod=test_view_isub>

    def test_view_isub(self):
        """view_isub"""
    
        print("")
        for itr in conf.get_variants({"memory_traits": [kokkos.Atomic]}):
            _shape = itr[0]
            _idx = itr[1]
            _zeros = itr[2]
            _kwargs = itr[3]
    
            _data = conf.generate_variant(_shape, **_kwargs)
    
            self._print_info(_data)
    
            _host = [_data[0].create_mirror_view(), _data[1].create_mirror_view()]
    
            _host[0][_idx] = 10
            _host[1][_idx] = 20
    
            _host[0][_idx] -= 3
            _host[1][_idx] -= 3
    
            _data[0].deep_copy(_host[0])
            _data[1].deep_copy(_host[1])
    
            self.assertEqual(_data[0].create_mirror_view()[_zeros], 0)
            self.assertEqual(_data[1].create_mirror_view()[_zeros], 0)
>           self.assertEqual(_data[0].create_mirror_view()[_idx], 7)
E           AssertionError: True != 7

kokkos/test/views.py:202: AssertionError

* compile using genuine `bool` type instead of an alias

* this seems to succeed at build stage, but a few tests do fail
at the moment

[skip ci]
@tylerjereddy tylerjereddy force-pushed the treddy_bool_alias_draft branch from f5d66e6 to d5c85c6 Compare October 26, 2022 15:41
* to accommodate `bool` view type, we use `True` instead
of actual integer values in a number of tests
@tylerjereddy
Copy link
Contributor Author

tylerjereddy commented Oct 26, 2022

Ok, tests are passing locally now with the "native" bool view type--we'll see if the CI agrees. If it does, please do check the testing changes carefully.

I think they make sense--basically any positive non-zero integer value should be considered True for testing purposes.

@tylerjereddy
Copy link
Contributor Author

Looks like a subset of CI CMake builds fail with: kokkos/core/src/impl/Kokkos_Atomic_View.hpp:218:73: error: ‘*’ in boolean context, suggest ‘&&’ instead [-Werror=int-in-bool-context]

@jrmadsen
Copy link
Contributor

Easy fix, in include/variants/atomics.hpp:

Exclude all meaningless/invalid arithmetic operations on booleans via an if constexpr, e.g.

  _atomic.def(
      "__mul__", [](atomic_type _obj, value_type _v) { return (_obj * _v); },
      py::is_operator());

should be:

  constexpr bool is_boolean = std::is_same<Tp, bool>::value;

  if constexpr(!is_boolean) {
    _atomic.def(
        "__mul__", [](atomic_type _obj, value_type _v) { return (_obj * _v); },
        py::is_operator());

    // ... etc
  }

Comment on lines +143 to +146
if _kwargs["dtype"] == kokkos.bool:
self.assertEqual(_data[1].create_mirror_view()[_idx], True)
else:
self.assertEqual(_data[1].create_mirror_view()[_idx], 2)
Copy link
Contributor

@jrmadsen jrmadsen Oct 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if _kwargs["dtype"] == kokkos.bool:
self.assertEqual(_data[1].create_mirror_view()[_idx], True)
else:
self.assertEqual(_data[1].create_mirror_view()[_idx], 2)
value = lambda v : v if _kwargs["dtype"] != kokkos.bool else v > 0
self.assertEqual(_data[1].create_mirror_view()[_idx], value(2))

Just thought this scheme would be easier to maintain + more compact

@tylerjereddy tylerjereddy changed the title WIP: add bool type (alias) WIP: add bool type Oct 26, 2022
@tylerjereddy
Copy link
Contributor Author

I think __mul__ should be allowed for bool though:

>>> import numpy as np
>>> np.array([True, True]) * np.array([False, False])
array([False, False])

If C++ doesn't allow it, I suppose we could disable it here and use casting in the ufunc inner loops in pykokkos proper.

@jrmadsen
Copy link
Contributor

jrmadsen commented Oct 27, 2022

@tylerjereddy sorry, disregard that statement. I saw something suggesting the compiler was trying to use atomic_fetch_add and atomic_fetch_sub and since the std::atomic docs on cppreference don't list any overloads for multiplication or division, I came to a wrong conclusion. C++ does allow multiplying bools and from the looks of your CI, the kokkos equivalent of the numpy multiplication you provided above is supported and passing -- the analogue to your failures would be something like np.array([True, True], dtype=np.atomicBool) if numpy supported atomic booleans.

@jrmadsen
Copy link
Contributor

I don't think this is necessarily an error. It is failing to build bc of -Werror=int-in-bool-context, i.e. you are using an integer value with a bool and allowing it to behave implicitly like a bool -- where any nonzero value is true. This might be valid in this context. I'd consult with Christian or Damien and see if they are fine with doing:

#if defined(__GNUC__)  // GCC and clang
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wint-in-bool-context"
#endif

// affected regions within generate_atomic_variant

#if defined(__GNUC__)  // GCC and clang
#pragma GCC diagnostic pop
#endif

@JBludau
Copy link
Contributor

JBludau commented Oct 27, 2022

Maybe I don't understand, but what would a multiplication of bools look like? I guess if you want to do this in cpp it will implicitly cast it to int, multiply and then cast it back ... which is the same as doing && for bool which is more expressive and actually well defined ... which is exactly what the warning suggests to do.
I think we should not pragma push the flag but provide correct specializations for bool as a type. Meaning having a specialized impl. that uses the &&

@JBludau
Copy link
Contributor

JBludau commented Oct 27, 2022

And if this is not possible, why not static_cast<bool>(myint) where necessary? this would be expressive at least and should disable the warning

@jrmadsen
Copy link
Contributor

And if this is not possible, why not static_cast<bool>(myint) where necessary? this would be expressive at least and should disable the warning

This would be ideal, I was under the impression from looking at the lambdas that atomic_type and the value_type were bools and the conversion to an int was happening in the operator overload.

@jrmadsen
Copy link
Contributor

Maybe I don't understand, but what would a multiplication of bools look like? I guess if you want to do this in cpp it will implicitly cast it to int, multiply and then cast it back ... which is the same as doing && for bool which is more expressive and actually well defined ... which is exactly what the warning suggests to do.
I think we should not pragma push the flag but provide correct specializations for bool as a type. Meaning having a specialized impl. that uses the &&

Agree in principal but you would need a partial specialization and this is a freestanding function

@jrmadsen
Copy link
Contributor

Oh wait nevermind, I remember seeing C++17 or higher is a requirement for Kokkos now so an if constexpr would work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants