KhronosGroup / KhronosGroup/SYCL-Docs

Explicit memory operations are underspecified

Open
#104 5 comments 0 reactions 0 assignees View on GitHub
clarification
Dominant language
JavaScript
Stars
158
Forks
80
Avg merge
7d 6h
Merged PRs (30d)
5

Description

I've recently started to look into explicit memory operations again, and have come to the conclusion that the exact semantics of the various functions are still rather underspecified.

Since I'm not quite happy with the current state of support for explicit memory operations in the existing SYCL implementations, I've also created [a PR for the CTS](https://github.com/KhronosGroup/SYCL-CTS/pull/58) that greatly enhances the respective tests, thoroughly checking all of the expected behaviors (or at least, my interpretation thereof). Notably, this also includes a table with results for different SYCL implementations and backends, which I will reference below, so I encourage you to go [check it out](https://github.com/KhronosGroup/SYCL-CTS/pull/58)!

So here is the list of my concerns:

- 5c3fd1be addressed a couple of bugs where the allowed combinations of accessors were artificially (and sometimes nonsensically) restricted by having only a single set of template parameters for both accessors (for example, both had to have the same access mode). The commit changed this, however in doing so, also permitted the two accessors to have different dimensionalities. My question is: Was this intentional? While some implementations do already support it, and I can certainly see use cases where this could come in handy, it seems like a rather specialized and low-level mechanism. I would argue that it introduces quite a bit of complexity for implementors (see my test cases), which makes it prone to bugs (see my results), for a relatively niche application. I think realistically, whoever needs such functionality could also just implement it as a custom kernel.
- In similar vein, the spec doesn't say anything about the shape of the source and destination accessors used in a device-to-device copy, only that the source must access at least as many bytes as the destination. Should it therefore be possible to copy between two 2D accessors of shape [16,32] and [32,16]?
- Since source and destination can have different data types, a strided copy could even become impossible for certain shape combinations. For example, what happens when I want to copy from a [4,1] `int32` accessor to a [8,2] `int8` accessor? Each "row" (dimension 0) of the destination accessor is only 16 bits wide, but we want to copy 32 bits into it. (Edit: Okay, I guess it can be done by reininterpreting the source first, then copying 8 bit elements - still, this again seems like a very fringe use case).
- If copies between different dimensionalities or differently shaped accessors should be possible, I think the spec should also clarify the semantics of such a copy. I think the most obvious interpretation would be to have each copied element maintain its relative linear id within the source and destination range, but I would argue that as long as its not specified, anything could be done here.
- While the allowed accesses modes are listed for source and destination accessors, it says nowhere which access _targets_ are legal. For instance, it doesn't make any sense to copy into a `local` accessor, as the accessor only exists within a single CGF, and it is not allowed to submit more than one action from within a CGF (e.g. a kernel). I also used to think it was possible to copy from a host accessor to a device accessor. It was then pointed out to me that a copy is considered a kernel in itself, and it is not allowed to use host accessors in device kernels. While that is fine, I think it wouldn't hurt to spell it out explicitly somewhere. Curiously, the commit message of 5c3fd1be seems to address local accessors, but the change itself appears to be missing from the diff.
- When copying from or to the host using a raw pointer or `shared_ptr`, should the host memory be considered dense? The spec says "if an accessor accesses a range of 10 elements of `int` type, the host pointer must at least have `10 * sizeof(int)` bytes of memory allocated". From this I would assume that copying the range [3,7] out of a [10,20] buffer at offset [2,5] would also only require `3 * 7 * sizeof(T)` bytes on the host, thus being a dense copy of the strided source data. However, according to my results not all implementations behave this way (granted, this could realistically simply be bugs).
- I think the example could be changed to a 2D buffer with a ranged accessor to illustrate this.
- Lastly, should it be possible to only `fill` parts of a buffer by using a ranged accessor? I'd find it rather unintuitive if not, but none of the implementations I've tested seems to support it.

Contributor guide

No contributing guide indexed for this repository

Research direction

Read the issue's list of explicit memory-operation questions alongside the linked SYCL-CTS PR #58 and its enhanced tests. Compare the tested behaviors with the current specification, then document decisions for accessor shapes, dimensionality, access targets, host memory layout, and ranged fills. Done means the semantics are resolved and the specification and tests agree.

Written by the indexing model from the issue text.

Assessment

Domain
documentation, testing-qa
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
15/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.