C++ AMP: discard_data on array_view before delete?
-
lundi 5 mars 2012 16:43
With Developer Preview, I had the following code running without trouble:
unsigned int* otherPixelsBWData = new unsigned int[size/2];
array_view<unsigned int> otherPixelsBW(size/2, reinterpret_cast<unsigned int*>(otherPixelsBWData));index<1> origin(0);
extent<1> e(size);
parallel_for_each(e, [=] (index<1> idx) restrict(amp)
{
...
});delete(otherPixelsBWData);
Now, with the Beta version of VS11, I get a System.AccessViolationException because of the delete (works fine without the delete).
I understand that the array_view is still mapped on my pointer, and isn't happy after the delete.
If I discard the data first, it works fine:
otherPixelsBW.discard_data();
delete(otherPixelsBWData);Now the question: is this use of discard_data safe? I didn't read anything about this way in the doc, but it is the only method I see to unmap the array_view.
Toutes les réponses
-
lundi 5 mars 2012 22:24
Hi PYB,
the documentation states:
When an array_view is created over a pointer in system memory, you commit to:
1. Only changing the view directly through the view class,
2. Or, adhering to the following rules when accessing the data directly (not through the view):
a. Calling synchronize() before the data is accessed directly,
b. And, if the underlying data is modified, calling refresh() prior to further accessing it through the view.So it does not specifically address the case of deleting the underlying pointer, although as you said yourself, this is dangerous.
In your code sample above I strongly suspect that the discard_data() call prevents the crash as this is preventing the otherwise implicit copying of the data from the GPU into the memory underlying the array_view on first access after the kernel execution.
-Thomas
-
lundi 5 mars 2012 22:31
Hi PYB_42,
Thanks for using C++ AMP. In your code, please note that the destructor of array_view otherPixelsBW is called after "delete" when otherPixelsBW is out of scope. Since you haven't synchronized otherPixelsBW yet (for example, call otherPixelsBW.synchronize()), the destructor will try to synchronize -- copy the data from GPU (the computation result of parallel_for_each) to host data "otherPixelsBWData" that is wrapped by array_view. However, since you have deleted "otherPixelsBWData", the destination of the copy is invalid. Therefore, you got Access Violation.
discard_data() is an optimization hint to the runtime that it may discard the original content of the array_view. Since the content is discarded, the destroctor of the array_view does not try to copy, so you don't see the AV. In fact, if you call the discard_data() after delete, you still won't see the AV. However, as pointed out, discard_data() is an optimization hint to the runtime, you should not rely on it to avoid the AV.
Essentially, as a good design, you need to make sure the array_view is destructed before the data it wraps. For example above, one way is not to new/delete the host data. Instead, using STL containers like std::vector. So the std::vector will be destructed after the array_view (that wraps the vector) is desctructed. Another way is to to wrap the code using array_view with scope, for example
unsigned int* otherPixelsBWData = new unsigned int[size/2]; { array_view<unsigned int> otherPixelsBW(size/2, reinterpret_cast<unsigned int*>(otherPixelsBWData)); parallel_for_each(e, [=] (index<1> idx) restrict(amp) { ... // use of otherPixelsBW }); } // otherPixelsBW is destructed here. delete(otherPixelsBWData);Thanks,
Weirong
- Proposé comme réponse DanielMothMicrosoft Employee, Owner mardi 6 mars 2012 00:10
- Marqué comme réponse PYB_42 mardi 6 mars 2012 07:28
-
mardi 6 mars 2012 07:36
Thanks everybody, I used the scope trick, it works fine now.
I don't use synchronize() on the array_view, because the array_view is first filled in an AMP function, then used as data in another parallel_for_each, but I don't need its data on the CPU.
I don't use STL because the main program is in C#, and most of the data are managed arrays. I pin the data with a pin_ptr in a C++ CLI project, before calling the functions of the C++ AMP project. But in the above case, it is only internal data.
-
mercredi 7 mars 2012 01:42
Hi PYB_42. Just to be clear. The scope trick makes sure the array_view is destructed before the data it wraps, which is a good thing. However, if you want to avoid copying the data back to CPU (during destruction, which is an implicit synchronize.), you still need to call discard_data to indicate this to runtime. My original response was to recommend you not to rely on discard_data to avoid the AV.
- Marqué comme réponse PYB_42 mercredi 7 mars 2012 07:34

