-
Notifications
You must be signed in to change notification settings - Fork 0
/
algorithm.h
109 lines (86 loc) · 5.05 KB
/
algorithm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/Pair.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#if 1
// added to vtkm: Pair.h
class ZipAdd{
public:
template<typename T, typename U>
vtkm::Pair<T, U> operator()(const vtkm::Pair<T, U>& a, const vtkm::Pair<T, U> &b)const
{
return vtkm::Pair<T,U>(a.first+b.first, a.second + b.second);
}
};
#endif
// TODO: custom Less()
template <class KeyType, class ValueType, class DeviceAdapter = VTKM_DEFAULT_DEVICE_ADAPTER_TAG>
void AverageByKey( const vtkm::cont::ArrayHandle<KeyType> &keyArray,
const vtkm::cont::ArrayHandle<ValueType> &valueArray,
vtkm::cont::ArrayHandle<KeyType> &outputKeyArray,
vtkm::cont::ArrayHandle<ValueType> &outputValueArray)
{
vtkm::cont::Timer<> timer;
vtkm::cont::ArrayHandle<ValueType> sumArray;
vtkm::cont::ArrayHandle<KeyType> keyArraySorted;
#if 0
vtkm::cont::ArrayHandle<ValueType> valueArraySorted;
cout << "AVG Time (s): " << timer.GetElapsedTime() << endl;
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Copy( keyArray, keyArraySorted );
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Copy( valueArray, valueArraySorted );
cout << "AVG Time (s): " << timer.GetElapsedTime() << endl;
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::SortByKey( keyArraySorted, valueArraySorted, std::less<KeyType>() ) ;
cout << "AVG Time (s): " << timer.GetElapsedTime() << endl;
vtkm::cont::ArrayHandleConstant<vtkm::Id> constOneArray(1, valueArray.GetNumberOfValues());
vtkm::cont::ArrayHandle<vtkm::Id> countArray;
auto inputZipHandle = vtkm::cont::make_ArrayHandleZip(valueArraySorted, constOneArray);
auto outputZipHandle = vtkm::cont::make_ArrayHandleZip(sumArray, countArray);
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::ReduceByKey( keyArraySorted, inputZipHandle,
outputKeyArray, outputZipHandle,
vtkm::internal::Add() );
#else
vtkm::cont::ArrayHandleCounting<vtkm::Id> indexArray(0, keyArray.GetNumberOfValues());
vtkm::cont::ArrayHandle<vtkm::Id> indexArraySorted;
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Copy( keyArray, keyArraySorted );
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Copy( indexArray, indexArraySorted );
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::SortByKey( keyArraySorted, indexArraySorted, std::less<KeyType>() ) ;
auto valueArraySorted
= vtkm::cont::make_ArrayHandlePermutation( indexArraySorted, valueArray );
vtkm::cont::ArrayHandleConstant<vtkm::Id> constOneArray(1, valueArray.GetNumberOfValues());
vtkm::cont::ArrayHandle<vtkm::Id> countArray;
#if 1 // reduce twice
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::ReduceByKey( keyArraySorted, valueArraySorted,
outputKeyArray, sumArray,
vtkm::internal::Add() );
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::ReduceByKey( keyArraySorted, constOneArray,
outputKeyArray, countArray,
vtkm::internal::Add() );
#else // use zip (slower)
auto inputZipHandle = vtkm::cont::make_ArrayHandleZip(valueArraySorted, constOneArray);
auto outputZipHandle = vtkm::cont::make_ArrayHandleZip(sumArray, countArray);
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::ReduceByKey( keyArraySorted, inputZipHandle,
outputKeyArray, outputZipHandle,
ZipAdd() );
#endif
#endif
cout << "AVG Time (s): " << timer.GetElapsedTime() << endl;
// cout << "AVG Time (s): " << timer.GetElapsedTime() << endl;
// vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::ReduceByKey( keyArraySorted, constOneArray, outputKeyArray, countArray,
// vtkm::internal::Add());
// Using local structure with templates : Only works after c++11
struct DivideWorklet: public vtkm::worklet::WorkletMapField{
typedef void ControlSignature(FieldIn<>, FieldIn<>, FieldOut<>);
typedef void ExecutionSignature(_1, _2, _3);
VTKM_EXEC_EXPORT void operator()(const ValueType &v, vtkm::Id &count, ValueType &vout) const
{ vout = v * (1./count); }
};
vtkm::worklet::DispatcherMapField<DivideWorklet >().Invoke(sumArray, countArray, outputValueArray);
}