-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCLWorkGroupSettings.hpp
145 lines (125 loc) · 3.12 KB
/
CLWorkGroupSettings.hpp
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#ifndef TCL_WORK_GROUP_SETTINGS_HPP
#define TCL_WORK_GROUP_SETTINGS_HPP
#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL\cl.h>
#endif
#include <vector>
#include "CLDeviceInformation.hpp"
namespace tcl
{
/**
* CLExecute::Runでワークグループの数を設定するためのクラス
* \tparam WORK_DIM ワークグループの次元数
*/
class CLWorkGroupSettings
{
protected:
cl_uint workDimension;
std::vector<size_t> globalWorker;
std::vector<size_t> globalOffset;
std::vector<size_t> localWorker;
private:
inline void OptimizeDimension(const CLDeviceInformation& device)
{
// 次元数を丸める
if (device.MaxWorkItemDimensions() < workDimension)
workDimension = device.MaxWorkItemDimensions();
}
inline void OptimizeVectors(const CLDeviceInformation& device, std::vector<size_t>& target)
{
// ワーカーの最大値以下になるように最適化
const auto& itemSizes = device.MaxWorkItemSizes();
size_t dimension = device.MaxWorkItemDimensions();
if (target.size() < dimension)
dimension = target.size();
for (size_t i = 0; i < dimension; ++i)
{
if (itemSizes[i] < target[i])
target[i] = itemSizes[i];
}
}
public:
/**
* 次元数を返す
*/
inline cl_uint Dimension() const
{
return workDimension;
}
/**
* ワーカーの次元数を設定する
*/
inline CLWorkGroupSettings& Dimension(const cl_uint dimention)
{
workDimension = dimention;
return *this;
}
inline size_t* WorkerRange()
{
return &globalWorker[0];
}
/**
* ワーカーの仕事をする範囲を設定する
*/
inline CLWorkGroupSettings& WorkerRange(const std::vector<size_t>& workerRange)
{
globalWorker = std::vector<size_t>(workerRange);
return *this;
}
inline size_t* Offset()
{
return &globalOffset[0];
}
/**
* ワーカーの初期実行位置を設定する
* \param[in] offset 初期実行位置の配列,長さは次元数に依存
*/
inline CLWorkGroupSettings& Offset(const std::vector<size_t>& offset)
{
globalOffset = std::vector<size_t>(offset);
return *this;
}
inline size_t* SplitSize()
{
return &localWorker[0];
}
/**
* ワーカーを小分けする数を設定する
*/
inline CLWorkGroupSettings& SplitSize(const std::vector<size_t>& splitSize)
{
localWorker = std::vector<size_t>(splitSize);
return *this;
}
/**
* 設定を最適化する
*/
CLWorkGroupSettings& Optimize(const CLDeviceInformation& device)
{
OptimizeDimension(device);
OptimizeVectors(device, globalWorker);
OptimizeVectors(device, globalOffset);
OptimizeVectors(device, localWorker);
return *this;
}
public:
/**
* CLExecute::Runでワークグループの数を設定するためのクラス
* \param[in] dimension ワークアイテムの次元数
* \param[in] workerSize ワークアイテムの大きさ,次元数ごとのアイテムの数
* \param[in] offset 次元数に応じた実行位置
* \param[in] splitSize ワークアイテム全体の区切り方
*/
CLWorkGroupSettings(const cl_uint dimension = 0, const std::vector<size_t>& offset = {}, const std::vector<size_t>& workerRange = {}, const std::vector<size_t>& splitSize = {})
:
workDimension(dimension),
globalWorker(workerRange),
globalOffset(offset),
localWorker(splitSize)
{
}
};
}
#endif