VTK-m  2.2
DeviceAdapterAlgorithmGeneral.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 
11 #ifndef vtk_m_cont_internal_DeviceAdapterAlgorithmGeneral_h
12 #define vtk_m_cont_internal_DeviceAdapterAlgorithmGeneral_h
13 
14 #include <vtkm/cont/ArrayHandle.h>
20 #include <vtkm/cont/BitField.h>
21 #include <vtkm/cont/Logging.h>
24 
27 
28 #include <vtkm/BinaryPredicates.h>
29 #include <vtkm/TypeTraits.h>
30 
31 #include <vtkm/internal/Windows.h>
32 
33 #include <type_traits>
34 
35 namespace vtkm
36 {
37 namespace cont
38 {
39 namespace internal
40 {
41 
100 template <class DerivedAlgorithm, class DeviceAdapterTag>
101 struct DeviceAdapterAlgorithmGeneral
102 {
103  //--------------------------------------------------------------------------
104  // Get Execution Value
105  // This method is used internally to get a single element from the execution
106  // array. Normally you would just use ArrayGetValue, but that functionality
107  // relies on the device adapter algorithm and would create a circular
108  // dependency.
109 private:
110  template <typename T, class CIn>
111  VTKM_CONT static T GetExecutionValue(const vtkm::cont::ArrayHandle<T, CIn>& input, vtkm::Id index)
112  {
114 
115  {
116  vtkm::cont::Token token;
117 
118  auto inputPortal = input.PrepareForInput(DeviceAdapterTag(), token);
119  auto outputPortal = output.PrepareForOutput(1, DeviceAdapterTag(), token);
120 
121  CopyKernel<decltype(inputPortal), decltype(outputPortal)> kernel(
122  inputPortal, outputPortal, index);
123 
124  DerivedAlgorithm::Schedule(kernel, 1);
125  }
126 
127  return output.ReadPortal().Get(0);
128  }
129 
130 public:
131  //--------------------------------------------------------------------------
132  // BitFieldToUnorderedSet
133  template <typename IndicesStorage>
134  VTKM_CONT static vtkm::Id BitFieldToUnorderedSet(
135  const vtkm::cont::BitField& bits,
137  {
139 
140  vtkm::Id numBits = bits.GetNumberOfBits();
141 
142  vtkm::cont::Token token;
143 
144  auto bitsPortal = bits.PrepareForInput(DeviceAdapterTag{}, token);
145  auto indicesPortal = indices.PrepareForOutput(numBits, DeviceAdapterTag{}, token);
146 
147  std::atomic<vtkm::UInt64> popCount;
148  popCount.store(0, std::memory_order_seq_cst);
149 
150  using Functor = BitFieldToUnorderedSetFunctor<decltype(bitsPortal), decltype(indicesPortal)>;
151  Functor functor{ bitsPortal, indicesPortal, popCount };
152 
153  DerivedAlgorithm::Schedule(functor, functor.GetNumberOfInstances());
154  DerivedAlgorithm::Synchronize();
155 
156  token.DetachFromAll();
157 
158  numBits = static_cast<vtkm::Id>(popCount.load(std::memory_order_seq_cst));
159 
160  indices.Allocate(numBits, vtkm::CopyFlag::On);
161  return numBits;
162  }
163 
164  //--------------------------------------------------------------------------
165  // Copy
166  template <typename T, typename U, class CIn, class COut>
167  VTKM_CONT static void Copy(const vtkm::cont::ArrayHandle<T, CIn>& input,
169  {
171 
172  vtkm::cont::Token token;
173 
174  const vtkm::Id inSize = input.GetNumberOfValues();
175  auto inputPortal = input.PrepareForInput(DeviceAdapterTag(), token);
176  auto outputPortal = output.PrepareForOutput(inSize, DeviceAdapterTag(), token);
177 
178  CopyKernel<decltype(inputPortal), decltype(outputPortal)> kernel(inputPortal, outputPortal);
179  DerivedAlgorithm::Schedule(kernel, inSize);
180  }
181 
182  //--------------------------------------------------------------------------
183  // CopyIf
184  template <typename T, typename U, class CIn, class CStencil, class COut, class UnaryPredicate>
185  VTKM_CONT static void CopyIf(const vtkm::cont::ArrayHandle<T, CIn>& input,
188  UnaryPredicate unary_predicate)
189  {
191 
192  VTKM_ASSERT(input.GetNumberOfValues() == stencil.GetNumberOfValues());
193  vtkm::Id arrayLength = stencil.GetNumberOfValues();
194 
196  IndexArrayType indices;
197 
198  {
199  vtkm::cont::Token token;
200 
201  auto stencilPortal = stencil.PrepareForInput(DeviceAdapterTag(), token);
202  auto indexPortal = indices.PrepareForOutput(arrayLength, DeviceAdapterTag(), token);
203 
204  StencilToIndexFlagKernel<decltype(stencilPortal), decltype(indexPortal), UnaryPredicate>
205  indexKernel(stencilPortal, indexPortal, unary_predicate);
206 
207  DerivedAlgorithm::Schedule(indexKernel, arrayLength);
208  }
209 
210  vtkm::Id outArrayLength = DerivedAlgorithm::ScanExclusive(indices, indices);
211 
212  {
213  vtkm::cont::Token token;
214 
215  auto inputPortal = input.PrepareForInput(DeviceAdapterTag(), token);
216  auto stencilPortal = stencil.PrepareForInput(DeviceAdapterTag(), token);
217  auto indexPortal = indices.PrepareForOutput(arrayLength, DeviceAdapterTag(), token);
218  auto outputPortal = output.PrepareForOutput(outArrayLength, DeviceAdapterTag(), token);
219 
220  CopyIfKernel<decltype(inputPortal),
221  decltype(stencilPortal),
222  decltype(indexPortal),
223  decltype(outputPortal),
224  UnaryPredicate>
225  copyKernel(inputPortal, stencilPortal, indexPortal, outputPortal, unary_predicate);
226  DerivedAlgorithm::Schedule(copyKernel, arrayLength);
227  }
228  }
229 
230  template <typename T, typename U, class CIn, class CStencil, class COut>
231  VTKM_CONT static void CopyIf(const vtkm::cont::ArrayHandle<T, CIn>& input,
234  {
236 
237  ::vtkm::NotZeroInitialized unary_predicate;
238  DerivedAlgorithm::CopyIf(input, stencil, output, unary_predicate);
239  }
240 
241  //--------------------------------------------------------------------------
242  // CopySubRange
243  template <typename T, typename U, class CIn, class COut>
244  VTKM_CONT static bool CopySubRange(const vtkm::cont::ArrayHandle<T, CIn>& input,
245  vtkm::Id inputStartIndex,
246  vtkm::Id numberOfElementsToCopy,
248  vtkm::Id outputIndex = 0)
249  {
251 
252  const vtkm::Id inSize = input.GetNumberOfValues();
253 
254  // Check if the ranges overlap and fail if they do.
255  if (input == output &&
256  ((outputIndex >= inputStartIndex &&
257  outputIndex < inputStartIndex + numberOfElementsToCopy) ||
258  (inputStartIndex >= outputIndex &&
259  inputStartIndex < outputIndex + numberOfElementsToCopy)))
260  {
261  return false;
262  }
263 
264  if (inputStartIndex < 0 || numberOfElementsToCopy < 0 || outputIndex < 0 ||
265  inputStartIndex >= inSize)
266  { //invalid parameters
267  return false;
268  }
269 
270  //determine if the numberOfElementsToCopy needs to be reduced
271  if (inSize < (inputStartIndex + numberOfElementsToCopy))
272  { //adjust the size
273  numberOfElementsToCopy = (inSize - inputStartIndex);
274  }
275 
276  const vtkm::Id outSize = output.GetNumberOfValues();
277  const vtkm::Id copyOutEnd = outputIndex + numberOfElementsToCopy;
278  if (outSize < copyOutEnd)
279  { //output is not large enough
280  if (outSize == 0)
281  { //since output has nothing, just need to allocate to correct length
282  output.Allocate(copyOutEnd);
283  }
284  else
285  { //we currently have data in this array, so preserve it in the new
286  //resized array
288  temp.Allocate(copyOutEnd);
289  DerivedAlgorithm::CopySubRange(output, 0, outSize, temp);
290  output = temp;
291  }
292  }
293 
294  vtkm::cont::Token token;
295 
296  auto inputPortal = input.PrepareForInput(DeviceAdapterTag(), token);
297  auto outputPortal = output.PrepareForInPlace(DeviceAdapterTag(), token);
298 
299  CopyKernel<decltype(inputPortal), decltype(outputPortal)> kernel(
300  inputPortal, outputPortal, inputStartIndex, outputIndex);
301  DerivedAlgorithm::Schedule(kernel, numberOfElementsToCopy);
302  return true;
303  }
304 
305  //--------------------------------------------------------------------------
306  // Count Set Bits
308  {
310 
311  vtkm::cont::Token token;
312 
313  auto bitsPortal = bits.PrepareForInput(DeviceAdapterTag{}, token);
314 
315  std::atomic<vtkm::UInt64> popCount;
316  popCount.store(0, std::memory_order_relaxed);
317 
318  using Functor = CountSetBitsFunctor<decltype(bitsPortal)>;
319  Functor functor{ bitsPortal, popCount };
320 
321  DerivedAlgorithm::Schedule(functor, functor.GetNumberOfInstances());
322  DerivedAlgorithm::Synchronize();
323 
324  return static_cast<vtkm::Id>(popCount.load(std::memory_order_seq_cst));
325  }
326 
327  //--------------------------------------------------------------------------
328  // Fill Bit Field (bool, resize)
329  VTKM_CONT static void Fill(vtkm::cont::BitField& bits, bool value, vtkm::Id numBits)
330  {
332 
333  if (numBits == 0)
334  {
335  bits.Allocate(0);
336  return;
337  }
338 
339  vtkm::cont::Token token;
340 
341  auto portal = bits.PrepareForOutput(numBits, DeviceAdapterTag{}, token);
342 
343  using WordType =
344  typename vtkm::cont::BitField::template ExecutionTypes<DeviceAdapterTag>::WordTypePreferred;
345 
346  using Functor = FillBitFieldFunctor<decltype(portal), WordType>;
347  Functor functor{ portal, value ? ~WordType{ 0 } : WordType{ 0 } };
348 
349  const vtkm::Id numWords = portal.template GetNumberOfWords<WordType>();
350  DerivedAlgorithm::Schedule(functor, numWords);
351  }
352 
353  //--------------------------------------------------------------------------
354  // Fill Bit Field (bool)
355  VTKM_CONT static void Fill(vtkm::cont::BitField& bits, bool value)
356  {
358 
359  const vtkm::Id numBits = bits.GetNumberOfBits();
360  if (numBits == 0)
361  {
362  return;
363  }
364 
365  vtkm::cont::Token token;
366 
367  auto portal = bits.PrepareForOutput(numBits, DeviceAdapterTag{}, token);
368 
369  using WordType =
370  typename vtkm::cont::BitField::template ExecutionTypes<DeviceAdapterTag>::WordTypePreferred;
371 
372  using Functor = FillBitFieldFunctor<decltype(portal), WordType>;
373  Functor functor{ portal, value ? ~WordType{ 0 } : WordType{ 0 } };
374 
375  const vtkm::Id numWords = portal.template GetNumberOfWords<WordType>();
376  DerivedAlgorithm::Schedule(functor, numWords);
377  }
378 
379  //--------------------------------------------------------------------------
380  // Fill Bit Field (mask, resize)
381  template <typename WordType>
382  VTKM_CONT static void Fill(vtkm::cont::BitField& bits, WordType word, vtkm::Id numBits)
383  {
385 
387 
388  if (numBits == 0)
389  {
390  bits.Allocate(0);
391  return;
392  }
393 
394  vtkm::cont::Token token;
395 
396  auto portal = bits.PrepareForOutput(numBits, DeviceAdapterTag{}, token);
397 
398  // If less than 32 bits, repeat the word until we get a 32 bit pattern.
399  // Using this for the pattern prevents races while writing small numbers
400  // to adjacent memory locations.
401  auto repWord = RepeatTo32BitsIfNeeded(word);
402  using RepWordType = decltype(repWord);
403 
404  using Functor = FillBitFieldFunctor<decltype(portal), RepWordType>;
405  Functor functor{ portal, repWord };
406 
407  const vtkm::Id numWords = portal.template GetNumberOfWords<RepWordType>();
408  DerivedAlgorithm::Schedule(functor, numWords);
409  }
410 
411  //--------------------------------------------------------------------------
412  // Fill Bit Field (mask)
413  template <typename WordType>
414  VTKM_CONT static void Fill(vtkm::cont::BitField& bits, WordType word)
415  {
418 
419  const vtkm::Id numBits = bits.GetNumberOfBits();
420  if (numBits == 0)
421  {
422  return;
423  }
424 
425  vtkm::cont::Token token;
426 
427  auto portal = bits.PrepareForOutput(numBits, DeviceAdapterTag{}, token);
428 
429  // If less than 32 bits, repeat the word until we get a 32 bit pattern.
430  // Using this for the pattern prevents races while writing small numbers
431  // to adjacent memory locations.
432  auto repWord = RepeatTo32BitsIfNeeded(word);
433  using RepWordType = decltype(repWord);
434 
435  using Functor = FillBitFieldFunctor<decltype(portal), RepWordType>;
436  Functor functor{ portal, repWord };
437 
438  const vtkm::Id numWords = portal.template GetNumberOfWords<RepWordType>();
439  DerivedAlgorithm::Schedule(functor, numWords);
440  }
441 
442  //--------------------------------------------------------------------------
443  // Fill ArrayHandle
444  template <typename T, typename S>
445  VTKM_CONT static void Fill(vtkm::cont::ArrayHandle<T, S>& handle, const T& value)
446  {
448 
449  const vtkm::Id numValues = handle.GetNumberOfValues();
450  if (numValues == 0)
451  {
452  return;
453  }
454 
455  vtkm::cont::Token token;
456 
457  auto portal = handle.PrepareForOutput(numValues, DeviceAdapterTag{}, token);
458  FillArrayHandleFunctor<decltype(portal)> functor{ portal, value };
459  DerivedAlgorithm::Schedule(functor, numValues);
460  }
461 
462  //--------------------------------------------------------------------------
463  // Fill ArrayHandle (resize)
464  template <typename T, typename S>
465  VTKM_CONT static void Fill(vtkm::cont::ArrayHandle<T, S>& handle,
466  const T& value,
467  const vtkm::Id numValues)
468  {
470  if (numValues == 0)
471  {
472  handle.ReleaseResources();
473  return;
474  }
475 
476  vtkm::cont::Token token;
477 
478  auto portal = handle.PrepareForOutput(numValues, DeviceAdapterTag{}, token);
479  FillArrayHandleFunctor<decltype(portal)> functor{ portal, value };
480  DerivedAlgorithm::Schedule(functor, numValues);
481  }
482 
483  //--------------------------------------------------------------------------
484  // Lower Bounds
485  template <typename T, class CIn, class CVal, class COut>
486  VTKM_CONT static void LowerBounds(const vtkm::cont::ArrayHandle<T, CIn>& input,
487  const vtkm::cont::ArrayHandle<T, CVal>& values,
489  {
491 
492  vtkm::Id arraySize = values.GetNumberOfValues();
493 
494  vtkm::cont::Token token;
495 
496  auto inputPortal = input.PrepareForInput(DeviceAdapterTag(), token);
497  auto valuesPortal = values.PrepareForInput(DeviceAdapterTag(), token);
498  auto outputPortal = output.PrepareForOutput(arraySize, DeviceAdapterTag(), token);
499 
500  LowerBoundsKernel<decltype(inputPortal), decltype(valuesPortal), decltype(outputPortal)> kernel(
501  inputPortal, valuesPortal, outputPortal);
502 
503  DerivedAlgorithm::Schedule(kernel, arraySize);
504  }
505 
506  template <typename T, class CIn, class CVal, class COut, class BinaryCompare>
507  VTKM_CONT static void LowerBounds(const vtkm::cont::ArrayHandle<T, CIn>& input,
508  const vtkm::cont::ArrayHandle<T, CVal>& values,
510  BinaryCompare binary_compare)
511  {
513 
514  vtkm::Id arraySize = values.GetNumberOfValues();
515 
516  vtkm::cont::Token token;
517 
518  auto inputPortal = input.PrepareForInput(DeviceAdapterTag(), token);
519  auto valuesPortal = values.PrepareForInput(DeviceAdapterTag(), token);
520  auto outputPortal = output.PrepareForOutput(arraySize, DeviceAdapterTag(), token);
521 
522  LowerBoundsComparisonKernel<decltype(inputPortal),
523  decltype(valuesPortal),
524  decltype(outputPortal),
525  BinaryCompare>
526  kernel(inputPortal, valuesPortal, outputPortal, binary_compare);
527 
528  DerivedAlgorithm::Schedule(kernel, arraySize);
529  }
530 
531  template <class CIn, class COut>
532  VTKM_CONT static void LowerBounds(const vtkm::cont::ArrayHandle<vtkm::Id, CIn>& input,
534  {
536 
537  DeviceAdapterAlgorithmGeneral<DerivedAlgorithm, DeviceAdapterTag>::LowerBounds(
538  input, values_output, values_output);
539  }
540 
541  //--------------------------------------------------------------------------
542  // Reduce
543 #ifndef VTKM_CUDA
544  // nvcc doesn't like the private class declaration so disable under CUDA
545 private:
546 #endif
547  template <typename T, typename BinaryFunctor>
548  class ReduceDecoratorImpl
549  {
550  public:
551  VTKM_CONT ReduceDecoratorImpl() = default;
552 
553  VTKM_CONT
554  ReduceDecoratorImpl(const T& initialValue, const BinaryFunctor& binaryFunctor)
555  : InitialValue(initialValue)
556  , ReduceOperator(binaryFunctor)
557  {
558  }
559 
560  template <typename Portal>
561  VTKM_CONT ReduceKernel<Portal, T, BinaryFunctor> CreateFunctor(const Portal& portal) const
562  {
563  return ReduceKernel<Portal, T, BinaryFunctor>(
564  portal, this->InitialValue, this->ReduceOperator);
565  }
566 
567  private:
568  T InitialValue;
569  BinaryFunctor ReduceOperator;
570  };
571 
572 public:
573  template <typename T, typename U, class CIn>
574  VTKM_CONT static U Reduce(const vtkm::cont::ArrayHandle<T, CIn>& input, U initialValue)
575  {
577 
578  return DerivedAlgorithm::Reduce(input, initialValue, vtkm::Add());
579  }
580 
581  template <typename T, typename U, class CIn, class BinaryFunctor>
582  VTKM_CONT static U Reduce(const vtkm::cont::ArrayHandle<T, CIn>& input,
583  U initialValue,
584  BinaryFunctor binary_functor)
585  {
587 
588  //Crazy Idea:
589  //We perform the reduction in two levels. The first level is performed by
590  //an `ArrayHandleDecorator` which reduces 16 input values and maps them to
591  //one value. The decorator array is then 1/16 the length of the input array,
592  //and we can use inclusive scan as the second level to compute the final
593  //result.
594  vtkm::Id length = (input.GetNumberOfValues() / 16);
595  length += (input.GetNumberOfValues() % 16 == 0) ? 0 : 1;
597  length, ReduceDecoratorImpl<U, BinaryFunctor>(initialValue, binary_functor), input);
598 
600  const U scanResult =
601  DerivedAlgorithm::ScanInclusive(reduced, inclusiveScanStorage, binary_functor);
602  return scanResult;
603  }
604 
605  //--------------------------------------------------------------------------
606  // Reduce By Key
607  template <typename T,
608  typename U,
609  class KIn,
610  class VIn,
611  class KOut,
612  class VOut,
613  class BinaryFunctor>
614  VTKM_CONT static void ReduceByKey(const vtkm::cont::ArrayHandle<T, KIn>& keys,
615  const vtkm::cont::ArrayHandle<U, VIn>& values,
617  vtkm::cont::ArrayHandle<U, VOut>& values_output,
618  BinaryFunctor binary_functor)
619  {
621 
622  using KeysOutputType = vtkm::cont::ArrayHandle<U, KOut>;
623 
624  VTKM_ASSERT(keys.GetNumberOfValues() == values.GetNumberOfValues());
625  const vtkm::Id numberOfKeys = keys.GetNumberOfValues();
626 
627  if (numberOfKeys <= 1)
628  { //we only have a single key/value so that is our output
629  DerivedAlgorithm::Copy(keys, keys_output);
630  DerivedAlgorithm::Copy(values, values_output);
631  return;
632  }
633 
634  //we need to determine based on the keys what is the keystate for
635  //each key. The states are start, middle, end of a series and the special
636  //state start and end of a series
638 
639  {
640  vtkm::cont::Token token;
641  auto inputPortal = keys.PrepareForInput(DeviceAdapterTag(), token);
642  auto keyStatePortal = keystate.PrepareForOutput(numberOfKeys, DeviceAdapterTag(), token);
643  ReduceStencilGeneration<decltype(inputPortal), decltype(keyStatePortal)> kernel(
644  inputPortal, keyStatePortal);
645  DerivedAlgorithm::Schedule(kernel, numberOfKeys);
646  }
647 
648  //next step is we need to reduce the values for each key. This is done
649  //by running an inclusive scan over the values array using the stencil.
650  //
651  // this inclusive scan will write out two values, the first being
652  // the value summed currently, the second being 0 or 1, with 1 being used
653  // when this is a value of a key we need to write ( END or START_AND_END)
654  {
656  vtkm::cont::ArrayHandle<U> reducedValues;
657 
658  auto scanInput = vtkm::cont::make_ArrayHandleZip(values, keystate);
659  auto scanOutput = vtkm::cont::make_ArrayHandleZip(reducedValues, stencil);
660 
661  DerivedAlgorithm::ScanInclusive(
662  scanInput, scanOutput, ReduceByKeyAdd<BinaryFunctor>(binary_functor));
663 
664  //at this point we are done with keystate, so free the memory
665  keystate.ReleaseResources();
666 
667  // all we need know is an efficient way of doing the write back to the
668  // reduced global memory. this is done by using CopyIf with the
669  // stencil and values we just created with the inclusive scan
670  DerivedAlgorithm::CopyIf(reducedValues, stencil, values_output, ReduceByKeyUnaryStencilOp());
671 
672  } //release all temporary memory
673 
674  // Don't bother with the keys_output if it's an ArrayHandleDiscard -- there
675  // will be a runtime exception in Unique() otherwise:
677  {
678  //find all the unique keys
679  DerivedAlgorithm::Copy(keys, keys_output);
680  DerivedAlgorithm::Unique(keys_output);
681  }
682  }
683 
684  //--------------------------------------------------------------------------
685  // Scan Exclusive
686  template <typename T, class CIn, class COut, class BinaryFunctor>
687  VTKM_CONT static T ScanExclusive(const vtkm::cont::ArrayHandle<T, CIn>& input,
689  BinaryFunctor binaryFunctor,
690  const T& initialValue)
691  {
693 
694  vtkm::Id numValues = input.GetNumberOfValues();
695  if (numValues <= 0)
696  {
697  output.ReleaseResources();
698  return initialValue;
699  }
700 
702  T result = DerivedAlgorithm::ScanInclusive(input, inclusiveScan, binaryFunctor);
703 
704  vtkm::cont::Token token;
705 
706  auto inputPortal = inclusiveScan.PrepareForInput(DeviceAdapterTag(), token);
707  auto outputPortal = output.PrepareForOutput(numValues, DeviceAdapterTag(), token);
708 
709  InclusiveToExclusiveKernel<decltype(inputPortal), decltype(outputPortal), BinaryFunctor>
710  inclusiveToExclusive(inputPortal, outputPortal, binaryFunctor, initialValue);
711 
712  DerivedAlgorithm::Schedule(inclusiveToExclusive, numValues);
713 
714  return binaryFunctor(initialValue, result);
715  }
716 
717  template <typename T, class CIn, class COut>
718  VTKM_CONT static T ScanExclusive(const vtkm::cont::ArrayHandle<T, CIn>& input,
720  {
722 
723  return DerivedAlgorithm::ScanExclusive(
725  }
726 
727  //--------------------------------------------------------------------------
728  // Scan Exclusive Extend
729  template <typename T, class CIn, class COut, class BinaryFunctor>
730  VTKM_CONT static void ScanExtended(const vtkm::cont::ArrayHandle<T, CIn>& input,
732  BinaryFunctor binaryFunctor,
733  const T& initialValue)
734  {
736 
737  vtkm::Id numValues = input.GetNumberOfValues();
738  if (numValues <= 0)
739  {
740  output.Allocate(1);
741  output.WritePortal().Set(0, initialValue);
742  return;
743  }
744 
746  T result = DerivedAlgorithm::ScanInclusive(input, inclusiveScan, binaryFunctor);
747 
748  vtkm::cont::Token token;
749 
750  auto inputPortal = inclusiveScan.PrepareForInput(DeviceAdapterTag(), token);
751  auto outputPortal = output.PrepareForOutput(numValues + 1, DeviceAdapterTag(), token);
752 
753  InclusiveToExtendedKernel<decltype(inputPortal), decltype(outputPortal), BinaryFunctor>
754  inclusiveToExtended(inputPortal,
755  outputPortal,
756  binaryFunctor,
757  initialValue,
758  binaryFunctor(initialValue, result));
759 
760  DerivedAlgorithm::Schedule(inclusiveToExtended, numValues + 1);
761  }
762 
763  template <typename T, class CIn, class COut>
764  VTKM_CONT static void ScanExtended(const vtkm::cont::ArrayHandle<T, CIn>& input,
766  {
768 
769  DerivedAlgorithm::ScanExtended(
771  }
772 
773  //--------------------------------------------------------------------------
774  // Scan Exclusive By Key
775  template <typename KeyT,
776  typename ValueT,
777  typename KIn,
778  typename VIn,
779  typename VOut,
780  class BinaryFunctor>
781  VTKM_CONT static void ScanExclusiveByKey(const vtkm::cont::ArrayHandle<KeyT, KIn>& keys,
784  const ValueT& initialValue,
785  BinaryFunctor binaryFunctor)
786  {
788 
789  VTKM_ASSERT(keys.GetNumberOfValues() == values.GetNumberOfValues());
790 
791  // 0. Special case for 0 and 1 element input
792  vtkm::Id numberOfKeys = keys.GetNumberOfValues();
793 
794  if (numberOfKeys == 0)
795  {
796  return;
797  }
798  else if (numberOfKeys == 1)
799  {
800  output.Allocate(1);
801  output.WritePortal().Set(0, initialValue);
802  return;
803  }
804 
805  // 1. Create head flags
806  //we need to determine based on the keys what is the keystate for
807  //each key. The states are start, middle, end of a series and the special
808  //state start and end of a series
810 
811  {
812  vtkm::cont::Token token;
813  auto inputPortal = keys.PrepareForInput(DeviceAdapterTag(), token);
814  auto keyStatePortal = keystate.PrepareForOutput(numberOfKeys, DeviceAdapterTag(), token);
815  ReduceStencilGeneration<decltype(inputPortal), decltype(keyStatePortal)> kernel(
816  inputPortal, keyStatePortal);
817  DerivedAlgorithm::Schedule(kernel, numberOfKeys);
818  }
819 
820  // 2. Shift input and initialize elements at head flags position to initValue
822  {
823  vtkm::cont::Token token;
824  auto inputPortal = values.PrepareForInput(DeviceAdapterTag(), token);
825  auto keyStatePortal = keystate.PrepareForInput(DeviceAdapterTag(), token);
826  auto tempPortal = temp.PrepareForOutput(numberOfKeys, DeviceAdapterTag(), token);
827 
828  ShiftCopyAndInit<ValueT,
829  decltype(inputPortal),
830  decltype(keyStatePortal),
831  decltype(tempPortal)>
832  kernel(inputPortal, keyStatePortal, tempPortal, initialValue);
833  DerivedAlgorithm::Schedule(kernel, numberOfKeys);
834  }
835  // 3. Perform a ScanInclusiveByKey
836  DerivedAlgorithm::ScanInclusiveByKey(keys, temp, output, binaryFunctor);
837  }
838 
839  template <typename KeyT, typename ValueT, class KIn, typename VIn, typename VOut>
840  VTKM_CONT static void ScanExclusiveByKey(const vtkm::cont::ArrayHandle<KeyT, KIn>& keys,
843  {
845 
846  DerivedAlgorithm::ScanExclusiveByKey(
847  keys, values, output, vtkm::TypeTraits<ValueT>::ZeroInitialization(), vtkm::Sum());
848  }
849 
850  //--------------------------------------------------------------------------
851  // Scan Inclusive
852  template <typename T, class CIn, class COut>
853  VTKM_CONT static T ScanInclusive(const vtkm::cont::ArrayHandle<T, CIn>& input,
855  {
857 
858  return DerivedAlgorithm::ScanInclusive(input, output, vtkm::Add());
859  }
860 
861 private:
862  template <typename T1, typename S1, typename T2, typename S2>
863  VTKM_CONT static bool ArrayHandlesAreSame(const vtkm::cont::ArrayHandle<T1, S1>&,
865  {
866  return false;
867  }
868 
869  template <typename T, typename S>
870  VTKM_CONT static bool ArrayHandlesAreSame(const vtkm::cont::ArrayHandle<T, S>& a1,
872  {
873  return a1 == a2;
874  }
875 
876 public:
877  template <typename T, class CIn, class COut, class BinaryFunctor>
878  VTKM_CONT static T ScanInclusive(const vtkm::cont::ArrayHandle<T, CIn>& input,
880  BinaryFunctor binary_functor)
881  {
883 
884  if (!ArrayHandlesAreSame(input, output))
885  {
886  DerivedAlgorithm::Copy(input, output);
887  }
888 
889  vtkm::Id numValues = output.GetNumberOfValues();
890  if (numValues < 1)
891  {
893  }
894 
895  {
896  vtkm::cont::Token token;
897 
898  auto portal = output.PrepareForInPlace(DeviceAdapterTag(), token);
899  using ScanKernelType = ScanKernel<decltype(portal), BinaryFunctor>;
900 
901 
902  vtkm::Id stride;
903  for (stride = 2; stride - 1 < numValues; stride *= 2)
904  {
905  ScanKernelType kernel(portal, binary_functor, stride, stride / 2 - 1);
906  DerivedAlgorithm::Schedule(kernel, numValues / stride);
907  }
908 
909  // Do reverse operation on odd indices. Start at stride we were just at.
910  for (stride /= 2; stride > 1; stride /= 2)
911  {
912  ScanKernelType kernel(portal, binary_functor, stride, stride - 1);
913  DerivedAlgorithm::Schedule(kernel, numValues / stride);
914  }
915  }
916 
917  return GetExecutionValue(output, numValues - 1);
918  }
919 
920  template <typename KeyT, typename ValueT, class KIn, class VIn, class VOut>
921  VTKM_CONT static void ScanInclusiveByKey(const vtkm::cont::ArrayHandle<KeyT, KIn>& keys,
924  {
926 
927  return DerivedAlgorithm::ScanInclusiveByKey(keys, values, values_output, vtkm::Add());
928  }
929 
930  template <typename KeyT, typename ValueT, class KIn, class VIn, class VOut, class BinaryFunctor>
931  VTKM_CONT static void ScanInclusiveByKey(const vtkm::cont::ArrayHandle<KeyT, KIn>& keys,
934  BinaryFunctor binary_functor)
935  {
937 
938  VTKM_ASSERT(keys.GetNumberOfValues() == values.GetNumberOfValues());
939  const vtkm::Id numberOfKeys = keys.GetNumberOfValues();
940 
941  if (numberOfKeys <= 1)
942  { //we only have a single key/value so that is our output
943  DerivedAlgorithm::Copy(values, values_output);
944  return;
945  }
946 
947  //we need to determine based on the keys what is the keystate for
948  //each key. The states are start, middle, end of a series and the special
949  //state start and end of a series
951 
952  {
953  vtkm::cont::Token token;
954  auto inputPortal = keys.PrepareForInput(DeviceAdapterTag(), token);
955  auto keyStatePortal = keystate.PrepareForOutput(numberOfKeys, DeviceAdapterTag(), token);
956  ReduceStencilGeneration<decltype(inputPortal), decltype(keyStatePortal)> kernel(
957  inputPortal, keyStatePortal);
958  DerivedAlgorithm::Schedule(kernel, numberOfKeys);
959  }
960 
961  //next step is we need to reduce the values for each key. This is done
962  //by running an inclusive scan over the values array using the stencil.
963  //
964  // this inclusive scan will write out two values, the first being
965  // the value summed currently, the second being 0 or 1, with 1 being used
966  // when this is a value of a key we need to write ( END or START_AND_END)
967  {
968  vtkm::cont::ArrayHandle<ValueT> reducedValues;
970  auto scanInput = vtkm::cont::make_ArrayHandleZip(values, keystate);
971  auto scanOutput = vtkm::cont::make_ArrayHandleZip(reducedValues, stencil);
972 
973  DerivedAlgorithm::ScanInclusive(
974  scanInput, scanOutput, ReduceByKeyAdd<BinaryFunctor>(binary_functor));
975  //at this point we are done with keystate, so free the memory
976  keystate.ReleaseResources();
977  DerivedAlgorithm::Copy(reducedValues, values_output);
978  }
979  }
980 
981  //--------------------------------------------------------------------------
982  // Sort
983  template <typename T, class Storage, class BinaryCompare>
984  VTKM_CONT static void Sort(vtkm::cont::ArrayHandle<T, Storage>& values,
985  BinaryCompare binary_compare)
986  {
988 
989  vtkm::Id numValues = values.GetNumberOfValues();
990  if (numValues < 2)
991  {
992  return;
993  }
994  vtkm::Id numThreads = 1;
995  while (numThreads < numValues)
996  {
997  numThreads *= 2;
998  }
999  numThreads /= 2;
1000 
1001  vtkm::cont::Token token;
1002 
1003  auto portal = values.PrepareForInPlace(DeviceAdapterTag(), token);
1004  using MergeKernel = BitonicSortMergeKernel<decltype(portal), BinaryCompare>;
1005  using CrossoverKernel = BitonicSortCrossoverKernel<decltype(portal), BinaryCompare>;
1006 
1007  for (vtkm::Id crossoverSize = 1; crossoverSize < numValues; crossoverSize *= 2)
1008  {
1009  DerivedAlgorithm::Schedule(CrossoverKernel(portal, binary_compare, crossoverSize),
1010  numThreads);
1011  for (vtkm::Id mergeSize = crossoverSize / 2; mergeSize > 0; mergeSize /= 2)
1012  {
1013  DerivedAlgorithm::Schedule(MergeKernel(portal, binary_compare, mergeSize), numThreads);
1014  }
1015  }
1016  }
1017 
1018  template <typename T, class Storage>
1019  VTKM_CONT static void Sort(vtkm::cont::ArrayHandle<T, Storage>& values)
1020  {
1022 
1023  DerivedAlgorithm::Sort(values, DefaultCompareFunctor());
1024  }
1025 
1026  //--------------------------------------------------------------------------
1027  // Sort by Key
1028  template <typename T, typename U, class StorageT, class StorageU>
1029  VTKM_CONT static void SortByKey(vtkm::cont::ArrayHandle<T, StorageT>& keys,
1031  {
1033 
1034  //combine the keys and values into a ZipArrayHandle
1035  //we than need to specify a custom compare function wrapper
1036  //that only checks for key side of the pair, using a custom compare functor.
1037  auto zipHandle = vtkm::cont::make_ArrayHandleZip(keys, values);
1038  DerivedAlgorithm::Sort(zipHandle, internal::KeyCompare<T, U>());
1039  }
1040 
1041  template <typename T, typename U, class StorageT, class StorageU, class BinaryCompare>
1042  VTKM_CONT static void SortByKey(vtkm::cont::ArrayHandle<T, StorageT>& keys,
1044  BinaryCompare binary_compare)
1045  {
1047 
1048  //combine the keys and values into a ZipArrayHandle
1049  //we than need to specify a custom compare function wrapper
1050  //that only checks for key side of the pair, using the custom compare
1051  //functor that the user passed in
1052  auto zipHandle = vtkm::cont::make_ArrayHandleZip(keys, values);
1053  DerivedAlgorithm::Sort(zipHandle, internal::KeyCompare<T, U, BinaryCompare>(binary_compare));
1054  }
1055 
1056  template <typename T,
1057  typename U,
1058  typename V,
1059  typename StorageT,
1060  typename StorageU,
1061  typename StorageV,
1062  typename BinaryFunctor>
1063  VTKM_CONT static void Transform(const vtkm::cont::ArrayHandle<T, StorageT>& input1,
1066  BinaryFunctor binaryFunctor)
1067  {
1069 
1070  vtkm::Id numValues = vtkm::Min(input1.GetNumberOfValues(), input2.GetNumberOfValues());
1071  if (numValues <= 0)
1072  {
1073  return;
1074  }
1075 
1076  vtkm::cont::Token token;
1077 
1078  auto input1Portal = input1.PrepareForInput(DeviceAdapterTag(), token);
1079  auto input2Portal = input2.PrepareForInput(DeviceAdapterTag(), token);
1080  auto outputPortal = output.PrepareForOutput(numValues, DeviceAdapterTag(), token);
1081 
1082  BinaryTransformKernel<decltype(input1Portal),
1083  decltype(input2Portal),
1084  decltype(outputPortal),
1085  BinaryFunctor>
1086  binaryKernel(input1Portal, input2Portal, outputPortal, binaryFunctor);
1087  DerivedAlgorithm::Schedule(binaryKernel, numValues);
1088  }
1089 
1090  //};
1091  //--------------------------------------------------------------------------
1092  // Unique
1093  template <typename T, class Storage>
1094  VTKM_CONT static void Unique(vtkm::cont::ArrayHandle<T, Storage>& values)
1095  {
1097 
1098  DerivedAlgorithm::Unique(values, vtkm::Equal());
1099  }
1100 
1101  template <typename T, class Storage, class BinaryCompare>
1102  VTKM_CONT static void Unique(vtkm::cont::ArrayHandle<T, Storage>& values,
1103  BinaryCompare binary_compare)
1104  {
1106 
1108  vtkm::Id inputSize = values.GetNumberOfValues();
1109 
1110  using WrappedBOpType = internal::WrappedBinaryOperator<bool, BinaryCompare>;
1111  WrappedBOpType wrappedCompare(binary_compare);
1112 
1113  {
1114  vtkm::cont::Token token;
1115  auto valuesPortal = values.PrepareForInput(DeviceAdapterTag(), token);
1116  auto stencilPortal = stencilArray.PrepareForOutput(inputSize, DeviceAdapterTag(), token);
1117  ClassifyUniqueComparisonKernel<decltype(valuesPortal),
1118  decltype(stencilPortal),
1119  WrappedBOpType>
1120  classifyKernel(valuesPortal, stencilPortal, wrappedCompare);
1121 
1122  DerivedAlgorithm::Schedule(classifyKernel, inputSize);
1123  }
1124 
1126 
1127  DerivedAlgorithm::CopyIf(values, stencilArray, outputArray);
1128 
1129  values.Allocate(outputArray.GetNumberOfValues());
1130  DerivedAlgorithm::Copy(outputArray, values);
1131  }
1132 
1133  //--------------------------------------------------------------------------
1134  // Upper bounds
1135  template <typename T, class CIn, class CVal, class COut>
1136  VTKM_CONT static void UpperBounds(const vtkm::cont::ArrayHandle<T, CIn>& input,
1137  const vtkm::cont::ArrayHandle<T, CVal>& values,
1139  {
1141 
1142  vtkm::Id arraySize = values.GetNumberOfValues();
1143 
1144  vtkm::cont::Token token;
1145 
1146  auto inputPortal = input.PrepareForInput(DeviceAdapterTag(), token);
1147  auto valuesPortal = values.PrepareForInput(DeviceAdapterTag(), token);
1148  auto outputPortal = output.PrepareForOutput(arraySize, DeviceAdapterTag(), token);
1149 
1150  UpperBoundsKernel<decltype(inputPortal), decltype(valuesPortal), decltype(outputPortal)> kernel(
1151  inputPortal, valuesPortal, outputPortal);
1152  DerivedAlgorithm::Schedule(kernel, arraySize);
1153  }
1154 
1155  template <typename T, class CIn, class CVal, class COut, class BinaryCompare>
1156  VTKM_CONT static void UpperBounds(const vtkm::cont::ArrayHandle<T, CIn>& input,
1157  const vtkm::cont::ArrayHandle<T, CVal>& values,
1159  BinaryCompare binary_compare)
1160  {
1162 
1163  vtkm::Id arraySize = values.GetNumberOfValues();
1164 
1165  vtkm::cont::Token token;
1166 
1167  auto inputPortal = input.PrepareForInput(DeviceAdapterTag(), token);
1168  auto valuesPortal = values.PrepareForInput(DeviceAdapterTag(), token);
1169  auto outputPortal = output.PrepareForOutput(arraySize, DeviceAdapterTag(), token);
1170 
1171  UpperBoundsKernelComparisonKernel<decltype(inputPortal),
1172  decltype(valuesPortal),
1173  decltype(outputPortal),
1174  BinaryCompare>
1175  kernel(inputPortal, valuesPortal, outputPortal, binary_compare);
1176 
1177  DerivedAlgorithm::Schedule(kernel, arraySize);
1178  }
1179 
1180  template <class CIn, class COut>
1181  VTKM_CONT static void UpperBounds(const vtkm::cont::ArrayHandle<vtkm::Id, CIn>& input,
1183  {
1185 
1186  DeviceAdapterAlgorithmGeneral<DerivedAlgorithm, DeviceAdapterTag>::UpperBounds(
1187  input, values_output, values_output);
1188  }
1189 };
1190 
1191 } // namespace internal
1192 
1203 template <typename DeviceTag>
1204 class DeviceTaskTypes
1205 {
1206 public:
1207  template <typename WorkletType, typename InvocationType>
1208  static vtkm::exec::internal::TaskSingular<WorkletType, InvocationType> MakeTask(
1209  WorkletType& worklet,
1210  InvocationType& invocation,
1211  vtkm::Id,
1212  vtkm::Id globalIndexOffset = 0)
1213  {
1214  using Task = vtkm::exec::internal::TaskSingular<WorkletType, InvocationType>;
1215  return Task(worklet, invocation, globalIndexOffset);
1216  }
1217 
1218  template <typename WorkletType, typename InvocationType>
1219  static vtkm::exec::internal::TaskSingular<WorkletType, InvocationType> MakeTask(
1220  WorkletType& worklet,
1221  InvocationType& invocation,
1222  vtkm::Id3,
1223  vtkm::Id globalIndexOffset = 0)
1224  {
1225  using Task = vtkm::exec::internal::TaskSingular<WorkletType, InvocationType>;
1226  return Task(worklet, invocation, globalIndexOffset);
1227  }
1228 };
1229 }
1230 } // namespace vtkm::cont
1231 
1232 #endif //vtk_m_cont_internal_DeviceAdapterAlgorithmGeneral_h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:300
ArrayHandle.h
FunctorsGeneral.h
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::TypeTraits
The TypeTraits class provides helpful compile-time information about the basic types used in VTKm (an...
Definition: TypeTraits.h:61
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
vtkm::Transform
auto Transform(const TupleType &&tuple, Function &&f) -> decltype(Apply(tuple, detail::TupleTransformFunctor(), std::forward< Function >(f)))
Construct a new vtkm::Tuple by applying a function to each value.
Definition: Tuple.h:213
BitField.h
TaskSingular.h
vtkm::cont::ArrayHandle::GetNumberOfValues
vtkm::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:468
vtkm::cont::BitField::GetNumberOfBits
vtkm::Id GetNumberOfBits() const
Return the number of bits stored by this BitField.
ArrayHandleView.h
ArrayHandleDecorator.h
Hints.h
ArrayHandleZip.h
vtkm::Add
Definition: Types.h:260
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
vtkm::cont::make_ArrayHandleZip
vtkm::cont::ArrayHandleZip< FirstHandleType, SecondHandleType > make_ArrayHandleZip(const FirstHandleType &first, const SecondHandleType &second)
A convenience function for creating an ArrayHandleZip.
Definition: ArrayHandleZip.h:290
TypeTraits.h
vtkm::Sum
Binary Predicate that takes two arguments argument x, and y and returns sum (addition) of the two val...
Definition: BinaryOperators.h:33
vtkm::cont::ArrayHandle::PrepareForInPlace
WritePortalType PrepareForInPlace(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares this array to be used in an in-place operation (both as input and output) in the execution e...
Definition: ArrayHandle.h:618
vtkm::Equal
Binary Predicate that takes two arguments argument x, and y and returns True if and only if x is equa...
Definition: BinaryPredicates.h:33
ArrayHandleIndex.h
ErrorMessageBuffer.h
VTKM_STATIC_ASSERT_MSG
#define VTKM_STATIC_ASSERT_MSG(condition, message)
Definition: StaticAssert.h:18
vtkm::cont::ArrayHandle::PrepareForOutput
WritePortalType PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares (allocates) this array to be used as an output from an operation in the execution environmen...
Definition: ArrayHandle.h:638
vtkm::cont::DeviceTaskTypes::MakeTask
static vtkm::exec::internal::TaskSingular< WorkletType, InvocationType > MakeTask(WorkletType &worklet, InvocationType &invocation, vtkm::Id3, vtkm::Id globalIndexOffset=0)
Definition: DeviceAdapterAlgorithmGeneral.h:1219
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::cont::ArrayHandle::ReleaseResources
void ReleaseResources() const
Releases all resources in both the control and execution environments.
Definition: ArrayHandle.h:584
vtkm::Id
vtkm::Int64 Id
Base type to use to index arrays.
Definition: Types.h:227
VTKM_LOG_SCOPE_FUNCTION
#define VTKM_LOG_SCOPE_FUNCTION(level)
Definition: Logging.h:214
vtkm::cont::BitField::Allocate
void Allocate(vtkm::Id numberOfBits, vtkm::CopyFlag preserve, vtkm::cont::Token &token) const
Allocate the requested number of bits.
vtkm::CopyFlag::On
@ On
vtkm::cont::Token::DetachFromAll
void DetachFromAll()
Detaches this Token from all resources to allow them to be used elsewhere or deleted.
vtkm::cont::BitField::PrepareForOutput
WritePortalType PrepareForOutput(vtkm::Id numBits, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares (allocates) this BitField to be used as an output from an operation in the execution environ...
vtkm::cont::ArrayHandle::ReadPortal
ReadPortalType ReadPortal() const
Get an array portal that can be used in the control environment.
Definition: ArrayHandle.h:433
vtkm::cont::BitField::IsValidWordType
detail::BitFieldTraits::IsValidWordType< WordType > IsValidWordType
Check whether a word type is valid for non-atomic operations.
Definition: BitField.h:525
vtkm::Vec< vtkm::Id, 3 >
vtkm::cont::BitField
Definition: BitField.h:497
vtkm::cont::IsArrayHandleDiscard
Helper to determine if an ArrayHandle type is an ArrayHandleDiscard.
Definition: ArrayHandleDiscard.h:183
vtkm::NotZeroInitialized
Predicate that takes a single argument x, and returns True if it isn't the identity of the Type T.
Definition: UnaryPredicates.h:32
vtkm::cont::BitField::PrepareForInput
ReadPortalType PrepareForInput(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares this BitField to be used as an input to an operation in the execution environment.
BinaryPredicates.h
ArrayHandleDiscard.h
vtkm::cont::ArrayHandle::PrepareForInput
ReadPortalType PrepareForInput(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares this array to be used as an input to an operation in the execution environment.
Definition: ArrayHandle.h:599
vtkm::TypeTraits::ZeroInitialization
static T ZeroInitialization()
A static function that returns 0 (or the closest equivalent to it) for the given type.
Definition: TypeTraits.h:77
vtkm::cont::DeviceTaskTypes::MakeTask
static vtkm::exec::internal::TaskSingular< WorkletType, InvocationType > MakeTask(WorkletType &worklet, InvocationType &invocation, vtkm::Id, vtkm::Id globalIndexOffset=0)
Definition: DeviceAdapterAlgorithmGeneral.h:1208
vtkm::cont::ArrayHandle::Allocate
void Allocate(vtkm::Id numberOfValues, vtkm::CopyFlag preserve, vtkm::cont::Token &token) const
Allocates an array large enough to hold the given number of values.
Definition: ArrayHandle.h:490
Logging.h
Logging utilities.
vtkm::cont::ArrayHandle::WritePortal
WritePortalType WritePortal() const
Get an array portal that can be used in the control environment.
Definition: ArrayHandle.h:454
Windows.h
vtkm::cont::LogLevel::Perf
@ Perf
General timing data and algorithm flow information, such as filter execution, worklet dispatches,...
vtkm::CountSetBits
vtkm::Int32 CountSetBits(vtkm::UInt32 word)
Count the total number of bits set in word.
Definition: Math.h:2940
vtkm::cont::make_ArrayHandleDecorator
ArrayHandleDecorator< typename std::decay< DecoratorImplT >::type, typename std::decay< ArrayTs >::type... > make_ArrayHandleDecorator(vtkm::Id numValues, DecoratorImplT &&f, ArrayTs &&... arrays)
Create an ArrayHandleDecorator with the specified number of values that uses the provided DecoratorIm...
Definition: ArrayHandleDecorator.h:694