Parallel Programming in Native Code

Parallel programming using C++ AMP, PPL and Agents libraries.

array_view without Data Source

array_view without Data Source

  • Comments 1

In Visual Studio 2012, C++ AMP introduced concurrency::array_view as a primary interface to read and write multi-dimensional data across the CPU and GPU accelerators.

The construction of array_view always required a data source like std::vector, concurrency::array etc. It could be either a CPU pointer or any data container that supports .data() and .size() methods . Even in the scenarios, where a temporary container is required purely as an output buffer and its initial content and backing memory allocation is irrelevant, it is mandated to provide a data source.

Look the below code snippets which illustrate the above point.

 

Example 1:

 1: array_view<const int, 1> arrViewA(M, vecA); // vecA is a const data source of type 'std::vector'
 2: array_view<const int, 1> arrViewB(M, vecB); // vecB is a const data source of type 'std::vector
 3:  
 4: std::vector<int> sumResult(arrViewA.extent.size());
 5: array_view<int, 1> arrViewSum(M,sumResult); // Creation of array_view with resource
 6: arrViewSum.discard_data();
 7:  
 8: parallel_for_each(arrViewSum.extent, [=](const index<1> &amp;idx) restrict(amp) {
 9:      arrViewSum[idx] = arrViewA[idx] + arrViewB[idx];
 10: });
 11: arrViewSum.synchronize();
 12:  
 13: for (size_t i = 0; i < sumResult.size(); ++i) {
 14:      sumResult[i]; // Accessing the result of computation
 15: }

 

 

Example 2:

 

 1: array_view<const int, 1> arrViewA(M, vecA); // vecA is a const data source of type 'std::vector'
 2: array_view<const int, 1> arrViewB(M, vecB); // vecB is a const data source of type 'std::vector'
 3:  
 4: array<int, 1> arrSumResult(arrViewA.extent); // Creating Array object as output buffer
 5: array_view<int, 1> arrViewSum(arrSumResult); // Creation of array_view over array
 6: arrViewSum.discard_data();
 7:  
 8: parallel_for_each(arrViewSum.extent, [=](const index<1> &amp;idx) restrict(amp) {
 9:       arrViewSum[idx] = arrViewA[idx] + arrViewB[idx];
 10: });
 11:  
 12: for (size_t i = 0; i < sumResult.size(); ++i) {
 13:       arrViewSum.data[i]; // Accessing the result of computation
 14: }

 

 

From the above code snippets, we will observe the following shortcomings:

a) Always a data source is required during to array_view construction

b) Requires the developers to learn about concurrency::array, array_view::discard_data.

c) Requires allocating the array on the right accelerator_view where, the array_view will be subsequently accessed. It also requires the users to specify the right accelerator_view to p_f_e, for using the array_view. Failure to specify the right accelerator_view may result in redundant data transfers to the targeted accelerator_view.

In Visual Studio 2013, these shortcomings have been addressed with the provision of “array_view construction without specifying a data source”. In short, this can be considered as creating an array_view, without any data source association and let the runtime allocate the underlying storage lazily as and when the array_view is accessed on accelerator_view or on the CPU.

- array_view without data source can be used only for read-write access. It cannot be constructed for read only purpose i.e., array_view<const T>.

- array_view without data source is just like any other ‘array_view’ object with no data association.

- array_view is initially uninitialized and behaves as if its contents have been “discard” immediately after construction.

- The “synchronize” API (the overload without any accelerator_view explicitly specified) will be a no-op for such an array_view.

Now, let’s rewrite the code snippets given in ‘Example 1’ and ‘Example 2’ using ‘array_view without data source’.

 1: array_view<const int, 1> arrViewA(M, vecA); // vecA is a const data source of type 'std::vector'
 2: array_view<const int, 1> arrViewB(M, vecB); // vecB is a const data source of type 'std::vector'
 3:  
 4: array_view<int, 1> arrViewSum(M); // Creation of array_view without data resource
 5:  
 6: parallel_for_each(arrViewSum.extent, [=](const index<1> &amp;idx) restrict(amp) {
 7:     arrViewSum[idx] = arrViewA[idx] + arrViewB[idx];
 8: });
 9:  
 10: for (size_t i = 0; i < arrViewSum.extent.size(); ++i) {
 11:     arrViewSum.data[i]; // Accessing the result of computation
 12: }

It is vividly evident that ‘array_view without data source’ is simple to use and in deed resulted in fewer lines of code :-)

 

In Closing

In this post we looked at the one of the improvements we’ve made to Array_views in Visual Studio 2013. Stay tuned for more blog posts on the improvements of C++ AMP in Visual Studio 2013. As usual, I would love to read your comments below or in our MSDN forum.

Blog - Comment List MSDN TechNet
  • Loading...
Leave a Comment
  • Please add 5 and 7 and type the answer here:
  • Post