Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
concurrency::array_view and concurrency::array are the most common vehicles for reading and writing data collections in your C++ AMP code. Often in your C++ AMP kernels or parts of your host code, some of the referenced data collections are purely inputs to the computation and are only read-from (never written-to) in that part of the code. This is the first post in a two part series, where we will look at how you can express the read-only nature of accesses for array_view/array input data collections in your C++ AMP code. In the second part, I will talk about why it is highly advisable to do so.
concurrency::array_view<const value_type, rank>
A concurrency::array_view object abstractly denotes a reference to an underlying source data container allocated on the host or an accelerator. Whether an array_view instance has read-only or read-write access to the underlying data is dictated by whether the value_type template argument of the array_view type is const qualified. For example, an array_view<const int> object denotes a read-only linear view of a dense collection of integers and can only be used to read the underlying data. An array_view<float, 2> object on the other hand, denotes a read-write 2D view of a dense collection of floats and can be used to both read-from and write-to the underlying data collection.
 int *ptr1 = new int[size];
 int *ptr2 = new int[size];
  
 array_view<const int> roArrView(size, ptr1);
  
 // An object of type array_view<const T> can only be read-from
 int firstElement = roArrView[0];
  
 // Compilation error: The underlying data cannot be modified through
 // an array_view<const T> object
 roArrView[0] = 5; // ERROR
  
 // An array_view<const T> object can be assigned to, to point
 // to different underlying data source
 roArrView = array_view<const int>(size, ptr2);
So if array_view<const value_type> denotes a read-only view of data, what does const array_view<value_type> denote? Well, it denotes the constness of the array_view object itself; i.e. whether the array_view object itself can be modified to reference a different underlying container (or even a different section of its current underlying container) than what it currently references. In other words, the assignment operator cannot be used on a const array_view<T> object to have it point to different underlying data than it currently does. As mentioned earlier, an array_view object just denotes a reference to an underlying data source and using the assignment operator on an array_view object just results in the array_view dropping the reference to its existing data source and start referencing a new data source (underlying the array_view object on the right-hand-side of the assignment operator).
 int *ptr1 = new int[size];
 int *ptr2 = new int[size];
  
 const array_view<int> constArrView(size, ptr1);
  
 // A const array_view<T> object can both read-from and write-to the
 // underlying data
 constArrView[0] = constArrView[1] + 1;
  
 // Compilation error: A const array_view<T> object cannot be modified to
 // point to different underlying data
 constArrView = array_view<int>(size, ptr2); // ERROR
  
 const array_view<const int> roConstArrView(size, ptr1);
  
 // A const array_view<const T> object can only be used to read the
 // underlying data
 int firstElement = roConstArrView[0];
  
 // Compilation error: a const array_view<const T> object cannot be used to
 // modify the underlying data
 roConstArrView[0] = 4; // ERROR
  
 // Compilation error: a const array_view<const T> object cannot be modified to
 // point to different underlying data
 roConstArrView = array_view<const int>(size, ptr2); // ERROR
This may be easier understood through an analogy with pointers. A pointer to const T (const T* ptr) denotes that the data pointed to (by the pointer) is constant and cannot be modified through the pointer. Analogously, array_view<const T> denotes that the referenced underlying data is constant (or read-only) and cannot be modified through the array_view object. On the other hand, a const pointer to T (T* const ptr) denotes that the pointer variable is constant and cannot be assigned a different address than what it currently points to. However, modifying the referenced data through the pointer is perfectly ok. Analogously, a const array_view<T> object denotes a constant array_view object and cannot be modified (using the assignment operator) to point to different underlying data than what it currently references. But the array_view has read-write access and can be used to modify the referenced data.
array_view type  | 
Analogous pointer type  | 
array_view<const T>  | 
const T*  | 
const array_view<T>  | 
T* const  | 
const array_view<const T>  | 
const T* const  | 
Finally, as you would expect, a read-only array_view (array_view<const T> ) object can be freely constructed from a read-write array_view (array_view<T> ) object. But constructing a read-write array_view from a read-only array_view would compromise the source array_view’s read-only restriction on the referenced data, and this unsafe operation is naturally disallowed.
 int *ptr1 = new int[size];
 const int *ptr2 = new int[size];
  
 // An array_view<const T> object can be constructed from a writable data source
 array_view<const int> roArrView(size, ptr1);
  
 array_view<int> rwArrView(size, ptr1);
  
 // A array_view<const T> object can be freely constructed from an
 // array_view<T> object
 array_view<const int> roArrView1 = rwArrView;
  
 parallel_for_each(roArrView1.extent, [=](index<1> idx) restrict(amp) {
     // The object roArrView is of type array_view<const int> and can only
     // be used to read the source data
     int temp = roArrView[idx];
  
     // Compilation error: Modifying the underlying data through
     // a array_view<const T> object is disallowed
     roArrView[idx] = temp + 5; // ERROR
 });
  
 // Compilation error: Cannot construct a array_view<T> over
 // a read-only data source (const int* ptr2)
 array_view rwArrView1(size, ptr2); // ERROR
  
 // Compilation error: Cannot construct a array_view<T> object from
 // a array_view<const T> object
 array_view rwArrView2(roArrView); // ERROR
const array<value_type, rank>
A concurrency::array object denotes a dense multi-dimensional data container allocated on a specific accelerator_view of a C++ AMP accelerator. Whether an array object is read-only or read-write is dictated by whether the array object or the C++ reference through which it is accessed is const qualified. For example, a const array<int> object denotes a read-only linear dense container of integers while an array<float, 2> object denotes a 2D dense container of floats. And if you are wondering what array<const T> denotes – it denotes nothing, is disallowed and will result in a compilation error.
Similar to array_view, the read-only restriction can be freely attributed by creating a const array<T> reference to an array<T> object. But, dropping the read-only restriction is unsafe (such as creating a non-const array<T> reference from a const array<T> object) and is disallowed per the normal C++ constness rules. It is worth noting here that an array object denotes the data container itself unlike an array_view object which denotes a reference to an underlying data source. Hence copy constructing an array objector assigning to an array object from another array object results in construction of new container with a deep copy of the source array contents unlike array_view copy construction or assignment which just results in the destination array_view to point to the same underlying data source as the source array_view object it is constructed or assigned from.
 int *ptr1 = new int[size];
  
 // An array denotes a data container and the contents of the source ptr1
 // are copied to the newly allocated memory
 array<int> rwArr(size, ptr1);
  
 // A const array<T> object denotes a read-only array
 const array<float> roArr(size, ptr1);
  
 // Read-onliness can be attributed by creating const reference
 // to a read-write array<T> object
 const array<int>& roArrRef = rwArr;
  
 parallel_for_each(roArrRef.extent, [&](index<1> idx) restrict(amp) {
     // Compilation error: roArrRef being a const array<int>& is read-only and
     // cannot be used to modify the array contents
     roArrRef[idx] = roArrRef[idx] + 5; // ERROR
 });
  
 // Compilation error: Constness of an array cannot be dropped
 array<float>& rwArrRef = roArr; // ERROR
 array<int>& rwArrRef2 = roArrRef; // ERROR
The concurrency::texture type has the same semantics as the array type with regard to constness; i.e. a const texture<T> object denotes read-only access to the texture data.
In closing
Having looked at how to specify the read-only restriction for array_view/array data collections in your C++ AMP code in this part, in the next part I will discuss the benefits of applying the read-only restriction when your array_view/array data collections are only read-from in a C++ AMP kernel or parts of your host code. I would love to hear your thoughts, comments, questions and feedback below or on our MSDN forum.