Skip to content

Commit 1103ce8

Browse files
Cleanup thread split interfaces. (#270)
Signed-off-by: Samuel K. Gutierrez <[email protected]>
1 parent 36df5fc commit 1103ce8

6 files changed

+99
-108
lines changed

src/quo-vadis-pthread.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ qv_pthread_scope_split(
6767
return QV_ERR_INVLD_ARG;
6868
}
6969
try {
70-
return scope->thsplit(
70+
return scope->thread_split(
7171
npieces, color_array, nthreads, QV_HW_OBJ_LAST, subscope
7272
);
7373
}

src/qvi-bbuff-rmi.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* a = size_t
1717
* b = qvi_bbuff_rmi_bytes_in_t, qvi_bbuff_rmi_bytes_out_t
1818
* c = hwloc_cpuset_t
19-
* c = qvi_hwloc_bitmap_s
19+
* c = qvi_hwloc_bitmap
2020
* d = qv_scope_create_hints_t
2121
* h = qvi_hwpool *
2222
* i = int
@@ -479,7 +479,7 @@ qvi_bbuff_rmi_pack_item(
479479
}
480480

481481
/**
482-
* Packs qvi_hwloc_bitmap_s
482+
* Packs qvi_hwloc_bitmap
483483
*/
484484
inline int
485485
qvi_bbuff_rmi_pack_item(
@@ -777,7 +777,7 @@ qvi_bbuff_rmi_unpack_item(
777777
}
778778

779779
/**
780-
* Unpacks qvi_hwloc_bitmap_s.
780+
* Unpacks qvi_hwloc_bitmap.
781781
*/
782782
inline int
783783
qvi_bbuff_rmi_unpack_item(

src/qvi-hwsplit.cc

+66-34
Original file line numberDiff line numberDiff line change
@@ -170,30 +170,6 @@ qvi_hwsplit::cpuset(void) const
170170
return m_hwpools[0]->cpuset();
171171
}
172172

173-
std::vector<pid_t> &
174-
qvi_hwsplit::tids(void)
175-
{
176-
return m_group_tids;
177-
}
178-
179-
std::vector<int> &
180-
qvi_hwsplit::colors(void)
181-
{
182-
return m_colors;
183-
}
184-
185-
std::vector<qvi_hwpool *> &
186-
qvi_hwsplit::hwpools(void)
187-
{
188-
return m_hwpools;
189-
}
190-
191-
qvi_hwloc_cpusets_t &
192-
qvi_hwsplit::affinities(void)
193-
{
194-
return m_affinities;
195-
}
196-
197173
int
198174
qvi_hwsplit::split_cpuset(
199175
qvi_hwloc_cpusets_t &result
@@ -218,6 +194,63 @@ qvi_hwsplit::split_cpuset(
218194
return rc;
219195
}
220196

197+
int
198+
qvi_hwsplit::thread_split(
199+
qv_scope_t *parent,
200+
uint_t npieces,
201+
int *kcolors,
202+
uint_t k,
203+
qv_hw_obj_type_t maybe_obj_type,
204+
qvi_hwpool ***khwpools
205+
) {
206+
const uint_t group_size = k;
207+
// Construct the hardware split.
208+
qvi_hwsplit hwsplit(parent, group_size, npieces, maybe_obj_type);
209+
// Eagerly make room for the group member information.
210+
hwsplit.reserve();
211+
// Since this is called by a single task, get its ID and associated
212+
// hardware affinity here, and replicate them in the following loop
213+
// that populates splitagg.
214+
//No point in doing this in a loop.
215+
const pid_t taskid = qvi_task::mytid();
216+
// Get the task's current affinity.
217+
hwloc_cpuset_t task_affinity = nullptr;
218+
int rc = parent->group()->task()->bind_top(&task_affinity);
219+
if (qvi_unlikely(rc != QV_SUCCESS)) return rc;
220+
// Prepare the hwsplit with our parent's information.
221+
for (uint_t i = 0; i < group_size; ++i) {
222+
// Store requested colors in aggregate.
223+
hwsplit.m_colors[i] = kcolors[i];
224+
// Since the parent hardware pool is the resource we are splitting and
225+
// agg_split_* calls expect |group_size| elements, replicate by dups.
226+
rc = qvi_dup(*parent->hwpool(), &hwsplit.m_hwpools[i]);
227+
if (qvi_unlikely(rc != QV_SUCCESS)) break;
228+
// Since this is called by a single task, replicate its task ID, too.
229+
hwsplit.m_group_tids[i] = taskid;
230+
// Same goes for the task's affinity.
231+
hwsplit.m_affinities[i].set(task_affinity);
232+
}
233+
// Cleanup: we don't need task_affinity anymore.
234+
qvi_hwloc_bitmap_delete(&task_affinity);
235+
if (qvi_unlikely(rc != QV_SUCCESS)) return rc;
236+
// Split the hardware resources based on the provided split parameters.
237+
rc = hwsplit.split();
238+
if (qvi_unlikely(rc != QV_SUCCESS)) return rc;
239+
// Now populate the hardware pools as the result.
240+
qvi_hwpool **ikhwpools = new qvi_hwpool *[group_size];
241+
for (uint_t i = 0; i < group_size; ++i) {
242+
// Copy out, since the hardware pools in splitagg will get freed.
243+
rc = qvi_dup(*hwsplit.m_hwpools[i], &ikhwpools[i]);
244+
if (qvi_unlikely(rc != QV_SUCCESS)) break;
245+
}
246+
if (qvi_unlikely(rc != QV_SUCCESS)) {
247+
delete[] ikhwpools;
248+
ikhwpools = nullptr;
249+
}
250+
*khwpools = ikhwpools;
251+
return rc;
252+
}
253+
221254
int
222255
qvi_hwsplit::osdev_cpusets(
223256
qvi_hwloc_cpusets_t &result
@@ -272,7 +305,6 @@ qvi_hwsplit::affinity_preserving_policy(void) const
272305
}
273306
}
274307

275-
/** Releases all devices contained in the provided split aggregate. */
276308
int
277309
qvi_hwsplit::release_devices(void)
278310
{
@@ -452,12 +484,12 @@ int
452484
qvi_hwsplit::split_affinity_preserving_pass1(void)
453485
{
454486
// cpusets used for first mapping pass.
455-
qvi_hwloc_cpusets_t cpusets{};
487+
qvi_hwloc_cpusets_t cpusets;
456488
// Get the primary cpusets used for the first pass of mapping.
457489
int rc = primary_cpusets(cpusets);
458490
if (rc != QV_SUCCESS) return rc;
459491
// Maintains the mapping between task (consumer) IDs and resource IDs.
460-
qvi_map_t map{};
492+
qvi_map_t map;
461493
// Map tasks based on their affinity to resources encoded by the cpusets.
462494
const auto policy = affinity_preserving_policy();
463495
rc = qvi_map_affinity_preserving(
@@ -735,24 +767,24 @@ qvi_hwsplit_coll::gather_hwpools(
735767
int
736768
qvi_hwsplit_coll::gather(void)
737769
{
738-
int rc = gather_values(qvi_task::mytid(), m_hwsplit.tids());
770+
int rc = gather_values(qvi_task::mytid(), m_hwsplit.m_group_tids);
739771
if (qvi_unlikely(rc != QV_SUCCESS)) return rc;
740-
rc = gather_values(m_color, m_hwsplit.colors());
772+
rc = gather_values(m_color, m_hwsplit.m_colors);
741773
if (qvi_unlikely(rc != QV_SUCCESS)) return rc;
742774
// Note that the result hwpools are copies, so we can modify them freely.
743-
rc = gather_hwpools(m_parent->hwpool(), m_hwsplit.hwpools());
775+
rc = gather_hwpools(m_parent->hwpool(), m_hwsplit.m_hwpools);
744776
if (qvi_unlikely(rc != QV_SUCCESS)) return rc;
745777

746778
const int myrank = m_parent->group()->rank();
747779
const uint_t group_size = m_parent->group()->size();
748780
if (myrank == qvi_hwsplit_coll::rootid) {
749-
m_hwsplit.affinities().resize(group_size);
781+
m_hwsplit.m_affinities.resize(group_size);
750782
for (uint_t tid = 0; tid < group_size; ++tid) {
751783
hwloc_cpuset_t cpuset = nullptr;
752784
rc = m_parent->group()->task()->bind_top(&cpuset);
753785
if (qvi_unlikely(rc != QV_SUCCESS)) break;
754786
//
755-
rc = m_hwsplit.affinities()[tid].set(cpuset);
787+
rc = m_hwsplit.m_affinities[tid].set(cpuset);
756788
// Clean up.
757789
qvi_hwloc_bitmap_delete(&cpuset);
758790
if (qvi_unlikely(rc != QV_SUCCESS)) break;
@@ -806,9 +838,9 @@ qvi_hwsplit_coll::scatter(
806838
int *colorp,
807839
qvi_hwpool **result
808840
) {
809-
const int rc = scatter_values(m_hwsplit.colors(), colorp);
841+
const int rc = scatter_values(m_hwsplit.m_colors, colorp);
810842
if (qvi_unlikely(rc != QV_SUCCESS)) return rc;
811-
return scatter_hwpools(m_hwsplit.hwpools(), result);
843+
return scatter_hwpools(m_hwsplit.m_hwpools, result);
812844
}
813845

814846
int

src/qvi-hwsplit.h

+20-31
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "qvi-hwpool.h"
2020
#include "qvi-map.h"
2121

22+
struct qvi_hwsplit_coll;
23+
2224
/**
2325
* Hardware split aggregation: a collection of information relevant to split
2426
* operations requiring aggregated (e.g., global) knowledge to perform a split.
@@ -30,6 +32,7 @@
3032
* this structure, but that isn't a requirement.
3133
*/
3234
struct qvi_hwsplit {
35+
friend qvi_hwsplit_coll;
3336
private:
3437
/** A pointer to my RMI. */
3538
qvi_rmi_client_t *m_rmi = nullptr;
@@ -92,18 +95,6 @@ struct qvi_hwsplit {
9295
*/
9396
qvi_hwloc_bitmap
9497
cpuset(void) const;
95-
/** Returns a reference to the group TIDs. */
96-
std::vector<pid_t> &
97-
tids(void);
98-
/** Returns a reference to the group colors. */
99-
std::vector<int> &
100-
colors(void);
101-
/** Returns a reference to the group hardware pools. */
102-
std::vector<qvi_hwpool *> &
103-
hwpools(void);
104-
/** Returns a reference to the group task affinities. */
105-
qvi_hwloc_cpusets_t &
106-
affinities(void);
10798
/**
10899
* Performs a straightforward splitting of the provided cpuset:
109100
* split the provided base cpuset into split_size distinct pieces.
@@ -112,9 +103,17 @@ struct qvi_hwsplit {
112103
split_cpuset(
113104
qvi_hwloc_cpusets_t &result
114105
) const;
115-
/**
116-
* Returns device affinities that are part of the split.
117-
*/
106+
/** Performs a thread-split operation, returns relevant hardare pools. */
107+
static int
108+
thread_split(
109+
qv_scope_t *parent,
110+
uint_t npieces,
111+
int *kcolors,
112+
uint_t k,
113+
qv_hw_obj_type_t maybe_obj_type,
114+
qvi_hwpool ***khwpools
115+
);
116+
/** Returns device affinities that are part of the split. */
118117
int
119118
osdev_cpusets(
120119
qvi_hwloc_cpusets_t &result
@@ -127,35 +126,25 @@ struct qvi_hwsplit {
127126

128127
qvi_map_fn_t
129128
affinity_preserving_policy(void) const;
130-
/** Releases all devices contained in the provided split aggregate. */
129+
/** Releases all devices contained in the hardware split. */
131130
int
132131
release_devices(void);
133-
/**
134-
* Straightforward user-defined device splitting.
135-
*/
132+
/** Straightforward user-defined device splitting. */
136133
int
137134
split_devices_user_defined(void);
138-
/**
139-
* Affinity preserving device splitting.
140-
*/
135+
/** Affinity preserving device splitting. */
141136
int
142137
split_devices_affinity_preserving(void);
143-
/**
144-
* User-defined split.
145-
*/
138+
/** User-defined split. */
146139
int
147140
split_user_defined(void);
148141

149142
int
150143
split_affinity_preserving_pass1(void);
151-
/**
152-
* Affinity preserving split.
153-
*/
144+
/** Affinity preserving split. */
154145
int
155146
split_affinity_preserving(void);
156-
/**
157-
* Splits aggregate scope data.
158-
*/
147+
/** Splits aggregate scope data. */
159148
int
160149
split(void);
161150
};

src/qvi-scope.cc

+8-38
Original file line numberDiff line numberDiff line change
@@ -264,46 +264,20 @@ qv_scope::split_at(
264264
}
265265

266266
int
267-
qv_scope::thsplit(
267+
qv_scope::thread_split(
268268
uint_t npieces,
269269
int *kcolors,
270270
uint_t k,
271271
qv_hw_obj_type_t maybe_obj_type,
272272
qv_scope_t ***thchildren
273273
) {
274274
*thchildren = nullptr;
275-
276275
const uint_t group_size = k;
277-
// Construct the hardware split.
278-
qvi_hwsplit hwsplit(this, group_size, npieces, maybe_obj_type);
279-
// Eagerly make room for the group member information.
280-
hwsplit.reserve();
281-
// Since this is called by a single task, get its ID and associated
282-
// hardware affinity here, and replicate them in the following loop
283-
// that populates splitagg.
284-
//No point in doing this in a loop.
285-
const pid_t taskid = qvi_task::mytid();
286-
hwloc_cpuset_t task_affinity = nullptr;
287-
// Get the task's current affinity.
288-
int rc = m_group->task()->bind_top(&task_affinity);
289-
if (rc != QV_SUCCESS) return rc;
290-
for (uint_t i = 0; i < group_size; ++i) {
291-
// Store requested colors in aggregate.
292-
hwsplit.colors()[i] = kcolors[i];
293-
// Since the parent hardware pool is the resource we are splitting and
294-
// agg_split_* calls expect |group_size| elements, replicate by dups.
295-
rc = qvi_dup(*m_hwpool, &hwsplit.hwpools()[i]);
296-
if (rc != QV_SUCCESS) break;
297-
// Since this is called by a single task, replicate its task ID, too.
298-
hwsplit.tids()[i] = taskid;
299-
// Same goes for the task's affinity.
300-
hwsplit.affinities()[i].set(task_affinity);
301-
}
302-
// Cleanup: we don't need task_affinity anymore.
303-
qvi_hwloc_bitmap_delete(&task_affinity);
304-
if (rc != QV_SUCCESS) return rc;
305-
// Split the hardware resources based on the provided split parameters.
306-
rc = hwsplit.split();
276+
// Split the hardware, get the hardare pools.
277+
qvi_hwpool **hwpools = nullptr;
278+
int rc = qvi_hwsplit::thread_split(
279+
this, npieces, kcolors, k, maybe_obj_type, &hwpools
280+
);
307281
if (rc != QV_SUCCESS) return rc;
308282
// Split off from our parent group. This call is called from a context in
309283
// which a process is splitting its resources across threads, so create a
@@ -314,13 +288,9 @@ qv_scope::thsplit(
314288
// Now create and populate the children.
315289
qv_scope_t **ithchildren = new qv_scope_t *[group_size];
316290
for (uint_t i = 0; i < group_size; ++i) {
317-
// Copy out, since the hardware pools in splitagg will get freed.
318-
qvi_hwpool *hwpool = nullptr;
319-
rc = qvi_dup(*hwsplit.hwpools()[i], &hwpool);
320-
if (rc != QV_SUCCESS) break;
321291
// Create and initialize the new scope.
322292
qv_scope_t *child = nullptr;
323-
rc = qvi_new(&child, thgroup, hwpool);
293+
rc = qvi_new(&child, thgroup, hwpools[i]);
324294
if (rc != QV_SUCCESS) break;
325295
thgroup->retain();
326296
ithchildren[i] = child;
@@ -344,7 +314,7 @@ qv_scope::thsplit_at(
344314
uint_t k,
345315
qv_scope_t ***kchildren
346316
) {
347-
return thsplit(hwpool_nobjects(type), kgroup_ids, k, type, kchildren);
317+
return thread_split(hwpool_nobjects(type), kgroup_ids, k, type, kchildren);
348318
}
349319

350320
/*

src/qvi-scope.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ struct qv_scope {
111111
);
112112

113113
int
114-
thsplit(
114+
thread_split(
115115
uint_t npieces,
116116
int *kcolors,
117117
uint_t k,

0 commit comments

Comments
 (0)