We have made several improvements to adding data into an `ArrayHandle`.
## Moving data from an `std::vector`
For numerous reasons, it is convenient to define data in a `std::vector`
and then wrap that into an `ArrayHandle`. It is often the case that an
`std::vector` is filled and then becomes unused once it is converted to an
`ArrayHandle`. In this case, what we really want is to pass the data off to
the `ArrayHandle` so that the `ArrayHandle` is now managing the data and
not the `std::vector`.
C++11 has a mechanism to do this: move semantics. You can now pass
variables to functions as an "rvalue" (right-hand value). When something is
passed as an rvalue, it can pull state out of that variable and move it
somewhere else. `std::vector` implements this movement so that an rvalue
can be moved to another `std::vector` without actually copying the data.
`make_ArrayHandle` now also takes advantage of this feature to move rvalue
`std::vector`s.
There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove`
that takes an rvalue. There is also a special overload of
`make_ArrayHandle` itself that handles an rvalue `vector`. (However, using
the explicit move version is better if you want to make sure the data is
actually moved.)
## Make `ArrayHandle` from initalizer list
A common use case for using `std::vector` (particularly in our unit tests)
is to quickly add an initalizer list into an `ArrayHandle`. Now you can
by simply passing an initializer list to `make_ArrayHandle`.
## Deprecated `make_ArrayHandle` with default shallow copy
For historical reasons, passing an `std::vector` or a pointer to
`make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`).
Although more efficient, this mode is inherintly unsafe, and making it the
default is asking for trouble.
To combat this, calling `make_ArrayHandle` without a copy flag is
deprecated. In this way, if you wish to do the faster but more unsafe
creation of an `ArrayHandle` you should explicitly express that.
This requried quite a few changes through the VTK-m source (particularly in
the tests).
## Similar changes to `Field`
`vtkm::cont::Field` has a `make_Field` helper function that is similar to
`make_ArrayHandle`. It also features the ability to create fields from
`std::vector`s and C arrays. It also likewise had the same unsafe behavior
by default of not copying from the source of the arrays.
That behavior has similarly been depreciated. You now have to specify a
copy flag.
The ability to construct a `Field` from an initializer list of values has
also been added.
While compiling UnitTestVariantArrayHandle, some versions of gcc
(between 6 and 8, I think) gave a warning like the following:
```
../vtkm/cont/StorageVirtual.h:227:12: warning: 'vtkm::Id vtkm::cont::internal::detail::StorageVirtualImpl<T, S>::GetNumberOfValues() const [with T = std::__cxx11::basic_string<char>; S = vtkm::cont::StorageTagImplicit<{anonymous}::UnusualPortal<std::__cxx11::basic_string<char> > >]' declared 'static' but never defined [-Wunused-function]
```
This warning makes no sense because it is refering to a method that is
not declared static. (In fact, it overrides a virtual method.)
I believe this is an obscure bug in these versions of gcc. I found a
[stackoverflow post] that seems to have the same problem, but no
workaround was found.
The warning originated from code that had little effect. It was part of
a test with a custom ArrayHandle storage type that was already disabled
for other reasons. Just removed the code.
[stackoverflow post]: https://stackoverflow.com/questions/56615695/how-to-fix-declared-static-but-never-defined-on-member-function
c689a68c5 Suppress bad deprecation warnings in MSVC
a3f23a03b Do not cast to ArrayHandleVirtual in VariantArrayHandle::CastAndCall
f6b13df51 Support coordinates of both float32 and float64
453e31404 Deprecate ArrayHandleVirtualCoordinates
be7f06bbe CoordinateSystem data is VariantArrayHandle
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2177
The Microsoft compiler has this annoying and stupid behavior where if
you have a generic templated method/function and that method is
instantiated with a deprecated class, then the compiler will issue a
C4996 warning even if the calling code is suppressing that warning
(because, for example, you are implementing other deprecated code and
the use is correct). There is no way around this other than suppressing
the warnings for all uses of the templated method.
A recent change to the continuous integration setup has caused
`UnitTestArrayPortalValueReference` to fail on one platform.
The problem was that the test was doing two unsafe things with the
right-shift assignment operator. The first unsafe thing was using itself
as the operand.
```cpp
ref >>= ref;
```
This causes clang to give a "self assign overload" warning. Using a
variable as its own operand for a compute assign operation isn't great
style, but for some operations it can cause weird errors. The reason for
the warning is that for a true integer shift operation, the compiler
will recognize that the result should be 0. So, when using this on base
integer types, you will get 0. But overloads can give you something
different, so that might lead to unexpected results. Because we _are_
using an overload (for the `ArrayPortalValueReference` class), the
compiler tells us we can get potentially unexpected results.
OK. That seems like something we can safely ignore (and were ignoring
for some time). After all, the whole point of the
`ArrayPortalValueReference` operators is to behave exactly the same as
the values they wrap. That brings us to the second unsafe thing the test
was doing: using an invalid value as the right hand operation. And this
is where things get weird.
The test was specifically failing when being run on `Int32`. It was
setting the underlying value for `ref` to be `1000` to start with. So
the expression `ref >>= ref` was trying to right shift `ref` by 1000
bits. Logically, this should of course give you 0. However, shifting a
number by more bits than exist causes undefined behavior (c.f.
https://wiki.sei.cmu.edu/confluence/display/c/INT34-C.+Do+not+shift+an+expression+by+a+negative+number+of+bits+or+by+greater+than+or+equal+to+the+number+of+bits+that+exist+in+the+operand).
You might not get back the expected value, and this is exactly what was
happening.
What I think happened was that the compiler determined that any valid
shift would be contained in 5 bits, so it truncated the value (1000) to
the least signifcant 5 bits (which happens to be 8). It then shifted
1000 by 8 and got the value 3 instead of 0.
The fix picks an operand number that is sure to be valid.
We are moving to deprecate `ArrayHandleVirtual`, so we are removing the
feature where `VariantArrayHandle::CastAndCall` automatically casts to
an `ArrayHandleVirtual` if possible.
The big reason to make this change now (as opposed to later when
`ArrayHandleVirtual` is deprecated) is to improve compile times.
This prevents us from having to compile an extra code path using
`ArrayHandleVirtual`.
`CoordinateSystem` differed from `Field` in that its `GetData`
method returned an `ArrayHandleVirtualCoordinates` instead of
a `VariantArrayHandle`. This is probably confusing since
`CoordianteSystem` inherits `Field` and has a pretty dramatic
difference in this behavior.
In preparation to deprecate `ArrayHandleVirtualCoordinates`, this
changes `CoordiantSystem` to be much more like `Field`. (In the
future, we may change the `CoordinateSystem` to point to a `Field`
rather than be a special `Field`.)
A method named `GetDataAsMultiplexer` has been added to
`CoordinateSystem`. This method allows you to get data from
`CoordinateSystem` as a single array type without worrying
about creating functors to handle different types and without
needing virtual methods.
18b5be92d Fix issue with CUDA and ArrayHandleMultiplexer
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard <robert.maynard@kitware.com>
Merge-request: !2168
As a programming convenience, all `vtkm::cont::DataSet` written by
`vtkm::io::VTKDataSetWriter` were written as a structured grid. Although
technically correct, it changed the structure of the data. This meant that
if you wanted to capture data to run elsewhere, it would run as a different
data type. This was particularly frustrating if the data of that structure
was causing problems and you wanted to debug it.
Now, `VTKDataSetWriter` checks the type of the `CoordinateSystem` to
determine whether the data should be written out as `STRUCTURED_POINTS`
(i.e. a uniform grid), `RECTILINEAR_GRID`, or `STRUCTURED_GRID`
(curvilinear).
`ArrayHandle::PrepareForOutput` often has to reallocate the array to the
specified size. Previously, this allocation was not happening with the
`Token` that is passed to `PrepareForOutput`. If the `ArrayHandle` is
already attached or enqueued for that `Token`, then the allocation would
deadlock.
You can now pass a `Token` object to `Allocate`, which is what
`PrepareForOutput` does.
When you try to call the `Reduce` operation in the CUDA device adapter
with a sufficently complex interator type, you get a compile error
that says `error: cannot pass an argument with a user-provided
copy-constructor to a device-side kernel launch`.
This appears to be a bug in either nvcc or Thrust. I believe it is
related to the following reported issues:
* https://github.com/thrust/thrust/issues/928
* https://github.com/thrust/thrust/issues/1044
Work around this problem by making a special condition for calling
`Reduce` with an `ArrayHandleMultiplexer` that calls the generic
algorithm in `DeviceAdapterAlgorithmGeneral` instead of the algorithm in
Thrust.
The implementation of LagrangianFilter uses some `ArrayHandle`s
declared as `static` in the .hxx header file. One of the bad
consequences of this is that there is no control over when the
arrays are freed. We have seen where these arrays get freed
after the CUDA system is closed, which causes nasty things to
happen as the program closes.
This works around the problem until a fix is implemnted.
Often when a user gives memory to an `ArrayHandle`, she wants data to be
written into the memory given to be used elsewhere. Previously, the
`Buffer` objects would delete the given buffer as soon as a write buffer
was created elsewhere. That was a problem if a user wants VTK-m to write
results right into a given buffer.
Instead, when a user provides memory, "pin" that memory so that the
`ArrayHandle` never deletes it.
The buffer class encapsulates the movement of raw C arrays between
host and devices.
The `Buffer` class itself is not associated with any device. Instead,
`Buffer` is used in conjunction with a new templated class named
`DeviceAdapterMemoryManager` that can allocate data on a given
device and transfer data as necessary. `DeviceAdapterMemoryManager`
will eventually replace the more complicated device adapter classes
that manage data on a device.
The code in `DeviceAdapterMemoryManager` is actually enclosed in
virtual methods. This allows us to limit the number of classes that
need to be compiled for a device. Rather, the implementation of
`DeviceAdapterMemoryManager` is compiled once with whatever compiler
is necessary, and then the `RuntimeDeviceInformation` is used to
get the correct object instance.
143e3d39a remove unused type alias
01a448663 Merge branch 'master' into uniform_real
c67e5bb12 fixe warnings about implicit type conversion
1e4294392 Add deterministic seed to avoid potential spurious failure
5b0e309b9 the random source is still 64 bits
cc3061bab Avoid calling ReadPortal() all the time
9bf6dea22 remove inline initialization of seed
e69308047 Add statistics base testing, add Flot32 RNG
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard <robert.maynard@kitware.com>
Merge-request: !2148
If a test throws any unexpected exception, the test is supposed to
detect that and fail. For the STL exceptions, the test failed to return
an error code. Fix that.
For some reason, `UnitTestContourTreeUniformAugmentedFilterCUDA` was
deadlocking on some of the dashboards when `VTKM_ASSERT` was changed to
be empty when compiling CUDA kernels (for compiler performance reasons).
Fix this by calling `assert` directly in this case.
For the life of me, I cannot figure out why this would be an issue.
Clearly the `assert` is never actually called or else the test would
error out (unless a special condition in CUDA is causing it to be
hidden). But if you take out the code, something changes to lock up the
kernel.
`assert` is supported on recent CUDA cards, but compiling it appears to be
very slow. By default, the `VTKM_ASSERT` macro has been disabled whenever
compiling for a CUDA device (i.e. when `__CUDA_ARCH__` is defined).
Asserts for CUDA devices can be turned back on by turning the
`VTKm_NO_ASSERT_CUDA` CMake variable off. Turning this CMake variable off
will enable assertions in CUDA kernels unless there is another reason
turning off all asserts (such as a release build).
The VS compiler gives a warning when you override a deprecated method.
Changed the StartScene and EndScene methods in Mapper to be non-virtual
with empty implementations. Deleted the corresponding methods from all
subclasses.
Many of the operations of `VariantArrayHandleBase` are not dependent on
the TypeList parameter of the class. Still others can operate just as
well by providing a type list to a method. Thus, it is convenient to
create a superclass that is not templated. That allows us to pass around
a `VariantArrayHandle` when the type list does not matter.
This superclass is called `VariantArrayHandleCommon` because "base" was
already taken.
This makes it clear that it returns true for an invalid array handle.
The previous name implied that it was looking for an ArrayHandle in some
"valid" set, which is the opposite.
0a4317709 Fix issues of calling __host__ from __device__
dd4d88cd5 Fix warnings about comparing floating point values
cd4b59059 Fix warnings about data type conversion
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard <robert.maynard@kitware.com>
Merge-request: !2146