Skip to content

Conversation

@AidanBeltonS
Copy link
Contributor

@AidanBeltonS AidanBeltonS commented Jul 28, 2022

This PR adds the marray<complex, N> specialization. The marray complex specialization is added using a mixture of free functions and deleting non applicable operators. This causes the marray interface to deviate slightly for the original sycl interface. The marray class is added in the sycl namespace to allow for proper specialization.

This additionally adds tests for the operators, interface, and free functions.

@AidanBeltonS AidanBeltonS marked this pull request as ready for review August 8, 2022 08:12
@AidanBeltonS
Copy link
Contributor Author

@TApplencourt this PR is now ready for review, testing of the marray type has been added.

@AidanBeltonS AidanBeltonS changed the title [WIP] Add initial marray implementation Add initial marray implementation Aug 22, 2022
@AerialMantis
Copy link

@TApplencourt friendly ping to request a review on this

@TApplencourt
Copy link
Collaborator

Oh thanks a lot for the ping. I totally miss Aidan previous message! Sorry about that

@AerialMantis
Copy link

No problem :)

@TApplencourt
Copy link
Collaborator

Sorry, Didn't forget about this! Will find the time to review this week

sycl::marray<complex<T>, NumElements>
make_complex_marray(const sycl::marray<T, NumElements> &real,
const sycl::marray<T, NumElements> &imag) {
sycl::marray<complex<T>, NumElements> rtn;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Stupid question, but can we not have a new array constructor? (and not a free function)

Comment on lines +1805 to +1827
template <class T, std::size_t NumElements>
sycl::marray<complex<T>, NumElements>
make_complex_marray(const sycl::marray<T, NumElements> &real, const T &imag) {
sycl::marray<complex<T>, NumElements> rtn;

for (std::size_t i = 0; i < NumElements; ++i) {
rtn[i].real(real[i]);
rtn[i].imag(imag);
}

return rtn;
}

template <class T, std::size_t NumElements>
sycl::marray<complex<T>, NumElements>
make_complex_marray(const T &real, const sycl::marray<T, NumElements> &imag) {
sycl::marray<complex<T>, NumElements> rtn;

for (std::size_t i = 0; i < NumElements; ++i) {
rtn[i].real(real);
rtn[i].imag(imag[i]);
}

Copy link
Collaborator

@TApplencourt TApplencourt Nov 4, 2022

Choose a reason for hiding this comment

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

Do we really want those? They sound super ugly... (and lead to bug in user-code)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, we can remove all make_complex_marray implementations.
I'll generate the marray test cases using the GENERATE macro from catch2.

// Test cases
  auto init_re = GENERATE(test_marray<T, NumElements>{
      1.0, 4.42, -3, 4.0, 2.02, inf_val<T>, inf_val<T>, 2.02, nan_val<T>,
      nan_val<T>, inf_val<T>, nan_val<T>, inf_val<T>, nan_val<T>});
  auto init_im = GENERATE(test_marray<T, NumElements>{
      1.0, 2.02, 3.5, -4.0, inf_val<T>, 4.42, nan_val<T>, 4.42, nan_val<T>,
      nan_val<T>, inf_val<T>, nan_val<T>, inf_val<T>, nan_val<T>});

  sycl::marray<sycl::ext::cplx::complex<T>, NumElements> cplx_input = sycl::ext::cplx::make_complex_marray(init_re.get(), init_im.get());

becomes

  auto cplx_input = GENERATE(sycl::marray<sycl::ext::cplx::complex<T>, NumElements>{
    sycl::ext::cplx::complex<T>{1.0, 1.0},
    sycl::ext::cplx::complex<T>{4.42, 2.02},
    sycl::ext::cplx::complex<T>{-3, 3.5},
    sycl::ext::cplx::complex<T>{4.0, -4.0},
    sycl::ext::cplx::complex<T>{2.02, inf_val<T>},
    sycl::ext::cplx::complex<T>{inf_val<T>, 4.42},
    sycl::ext::cplx::complex<T>{inf_val<T>, nan_val<T>},
    sycl::ext::cplx::complex<T>{2.02, 4.42},
    sycl::ext::cplx::complex<T>{nan_val<T>, nan_val<T>},
    sycl::ext::cplx::complex<T>{nan_val<T>, nan_val<T>},
    sycl::ext::cplx::complex<T>{inf_val<T>, inf_val<T>},
    sycl::ext::cplx::complex<T>{nan_val<T>, nan_val<T>},
    sycl::ext::cplx::complex<T>{inf_val<T>, inf_val<T>},
    sycl::ext::cplx::complex<T>{nan_val<T>, nan_val<T>},
  });

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks! I would like to keep this namespace as small as possible. Extending CATCH2 Macro sound like a good path :)


// Get

template <class T, std::size_t NumElements>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we have those free functions?
Why nover overlead .real() on marray to return those?

Copy link
Contributor

@jle-quel jle-quel Nov 8, 2022

Choose a reason for hiding this comment

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

I can also remove the Getter and Setter.
There is no real neither imag methods for the specialisation of the marray

Would you prefer not to have these functionalities on marray (just delete it)
Or implement real and imag methods on the marray specialization?

real() -> sycl::marray<T, NumElements> // getter
imag() -> sycl::marray<T, NumElements> // getter

real(sycl::marray<T, NumElements>)  // setter
imag(sycl::marray<T, NumElements>) // setter

Copy link
Contributor

@jle-quel jle-quel Nov 10, 2022

Choose a reason for hiding this comment

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

@TApplencourt ☝️ ?

Copy link
Collaborator

@TApplencourt TApplencourt Nov 11, 2022

Choose a reason for hiding this comment

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

Or implement real and imag methods on the marray specialization?

This sound cleaner to me! (sorry for the delay)

Copy link
Contributor

Choose a reason for hiding this comment

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

Here's the list of all getters and setters proposed in this PR:

// getter functions
sycl::marray<T, NumElements> real();
sycl::marray<T, NumElements> imag();
T real(std::size_t index);
T imag(std::size_t index);
template <std::size_t... I> auto constexpr real(std::integer_sequence<std::size_t, I...> int_seq);
template <std::size_t... I> auto constexpr imag(std::integer_sequence<std::size_t, I...> int_seq)

// setter functions
void real(const sycl::marray<T, NumElements> &values);
void imag(const sycl::marray<T, NumElements> &values);
void real(const T &value);
void imag(const T &value);
void real(std::size_t index, const T &value);
void imag(std::size_t index, const T &value);

One problem with overloading the real and imag for both getters and
setters is that we will create an ambiguous situation since overload resolution
doesn't depend on return values, but only arguments.

  • getter: T real(std::size_t index);
  • setter: void real(const T &value);

What we could do is to keep the getX and setX and overload them, or
other variants like implicit (ex: real) for getter and explicit
(ex: setReal) for setters.

What do you think?

Copy link
Collaborator

@TApplencourt TApplencourt Nov 15, 2022

Choose a reason for hiding this comment

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

I think keeping real() / imag() as a getter is a good idea (it mimic std::complex )
(By the way, do we need real(std::size_t index) I guess we can always do a[i].real()?)

For setting, this is a good question... Can we just do like std::complex? Aka, just use &=?

If the user passes a std::marray<complex> we set both real and imaging, and if just a std::marray<float>, we set just the real part. If people want to set a particular value a[i]=23 should do the trick.

What do you think?

Copy link
Contributor

@jle-quel jle-quel Nov 16, 2022

Choose a reason for hiding this comment

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

Since we are starting to rethink the design of the marray implementation, I believe we should do this as part of the DPC++ and Khronos proposal.

I'll update the marray's DPC++ proposal, and I'll ping you there so we can continue our discussion together with the community as well.

Then, we'll take back the decision made in the proposal, and I'll update the implementation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Good idea; thanks a lot!

@TApplencourt
Copy link
Collaborator

Thanks a lot, and sorry for all the stupid naive questions!

test_marray<T, NumElements> init_im1, \
test_marray<T, NumElements> init_re2, \
test_marray<T, NumElements> init_im2) { \
auto *cplx_inout = sycl::malloc_shared< \
Copy link
Contributor

Choose a reason for hiding this comment

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

Memory leak, cplx_inout is not freed

@jle-quel
Copy link
Contributor

jle-quel commented Feb 6, 2023

Due to the new PR introducing the restructured marray implementation, I will close this PR.

Please refer to the new PR #33,

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.

4 participants