1
- use mpi:: collective:: SystemOperation ;
2
1
use std:: borrow:: Borrow ;
3
2
3
+ use mpi:: collective:: SystemOperation ;
4
4
use mpi:: datatype:: { Partition , PartitionMut } ;
5
5
use mpi:: traits:: * ;
6
6
use mpi:: Rank ;
7
+ use num:: Zero ;
7
8
8
9
/// A very inefficient sorting algorithm that just gathers all data, sorts it locally and
9
10
/// re-distributes it. This is technically worse than the theoretical alternative and matrix-sort
@@ -15,10 +16,15 @@ use mpi::Rank;
15
16
/// - `comm` mpi communicator
16
17
/// - `data` partial data of this process. Must not be very much and must be of equal size on all
17
18
/// processes. The buffer will be overwritten with the sorted data
18
- pub fn inefficient_sort ( comm : & dyn Communicator , data : & mut [ u64 ] ) {
19
+ pub fn inefficient_sort < T > ( comm : & dyn Communicator , data : & mut [ T ] )
20
+ where
21
+ T : Clone + Ord + Zero ,
22
+ [ T ] : Buffer + BufferMut ,
23
+ Vec < T > : Buffer + BufferMut ,
24
+ {
19
25
let rank = comm. rank ( ) as usize ;
20
26
let world_size = comm. size ( ) as usize ;
21
- let mut recv_buffer = vec ! [ 0u64 ; data. len( ) * world_size] ;
27
+ let mut recv_buffer = vec ! [ T :: zero ( ) ; data. len( ) * world_size] ;
22
28
let root = comm. process_at_rank ( 0 ) ;
23
29
24
30
if rank == 0 {
@@ -42,7 +48,12 @@ pub fn inefficient_sort(comm: &dyn Communicator, data: &mut [u64]) {
42
48
///
43
49
/// # Returns
44
50
/// A vector containing the p-th part of the sorted data, where p is the count of processes
45
- pub fn inefficient_sort_var ( comm : & dyn Communicator , data : & [ u64 ] ) -> Vec < u64 > {
51
+ pub fn inefficient_sort_var < T > ( comm : & dyn Communicator , data : & [ T ] ) -> Vec < T >
52
+ where
53
+ T : Clone + Ord + Zero ,
54
+ [ T ] : Buffer + BufferMut ,
55
+ Vec < T > : Buffer + BufferMut ,
56
+ {
46
57
let rank = comm. rank ( ) as usize ;
47
58
let world_size = comm. size ( ) as usize ;
48
59
@@ -59,7 +70,7 @@ pub fn inefficient_sort_var(comm: &dyn Communicator, data: &[u64]) -> Vec<u64> {
59
70
}
60
71
61
72
let mut recv_buffer =
62
- vec ! [ 0u64 ; ( displs[ world_size - 1 ] + counts[ world_size - 1 ] ) as usize ] ;
73
+ vec ! [ T :: zero ( ) ; ( displs[ world_size - 1 ] + counts[ world_size - 1 ] ) as usize ] ;
63
74
let mut partition = PartitionMut :: new ( & mut recv_buffer, counts. borrow ( ) , displs. borrow ( ) ) ;
64
75
comm. this_process ( )
65
76
. gather_varcount_into_root ( data, & mut partition) ;
@@ -82,7 +93,7 @@ pub fn inefficient_sort_var(comm: &dyn Communicator, data: &[u64]) -> Vec<u64> {
82
93
let mut data_size: i32 = 0 ;
83
94
comm. this_process ( )
84
95
. scatter_into_root ( & counts, & mut data_size) ;
85
- let mut data = vec ! [ 0u64 ; data_size as usize ] ;
96
+ let mut data = vec ! [ T :: zero ( ) ; data_size as usize ] ;
86
97
comm. this_process ( )
87
98
. scatter_varcount_into_root ( & partition, & mut data) ;
88
99
data
@@ -92,7 +103,7 @@ pub fn inefficient_sort_var(comm: &dyn Communicator, data: &[u64]) -> Vec<u64> {
92
103
93
104
let mut data_size: i32 = 0 ;
94
105
comm. process_at_rank ( 0 ) . scatter_into ( & mut data_size) ;
95
- let mut data = vec ! [ 0u64 ; data_size as usize ] ;
106
+ let mut data = vec ! [ T :: zero ( ) ; data_size as usize ] ;
96
107
comm. process_at_rank ( 0 ) . scatter_varcount_into ( & mut data) ;
97
108
data
98
109
}
@@ -101,16 +112,19 @@ pub fn inefficient_sort_var(comm: &dyn Communicator, data: &[u64]) -> Vec<u64> {
101
112
/// Rank data locally with stable tie breaking. The resulting ranks are a permutation of the series ``0..n``. The
102
113
/// ranking requires time ``O(n*log(n))``. The resulting vector contains the ranks in the order of elements in ``data``,
103
114
/// with ties broken in order of appearance.
104
- fn local_rank ( data : & [ u64 ] ) -> Vec < u64 > {
115
+ fn local_rank < T > ( data : & [ T ] ) -> Vec < usize >
116
+ where
117
+ T : Clone + Ord ,
118
+ {
105
119
let mut sorted_data = data. to_vec ( ) ;
106
120
let mut ranking = Vec :: with_capacity ( data. len ( ) ) ;
107
121
sorted_data. sort_unstable ( ) ;
108
122
109
123
let mut tie_breaker = vec ! [ 0usize ; data. len( ) ] ;
110
124
111
125
for i in 0 ..data. len ( ) {
112
- let partition = sorted_data. partition_point ( |& x| x < data[ i] ) ;
113
- ranking. push ( ( partition + tie_breaker[ partition] ) as u64 ) ;
126
+ let partition = sorted_data. partition_point ( |x| x. clone ( ) < data[ i] ) ;
127
+ ranking. push ( partition + tie_breaker[ partition] ) ;
114
128
tie_breaker[ partition] += 1 ;
115
129
}
116
130
@@ -125,15 +139,20 @@ fn local_rank(data: &[u64]) -> Vec<u64> {
125
139
/// - `comm` mpi communicator
126
140
/// - `data` partial data of this process
127
141
/// - `ranking` output parameter for the ranking, must be of equal size as the data slice
128
- pub fn inefficient_rank ( comm : & dyn Communicator , data : & [ u64 ] , ranking : & mut [ u64 ] ) {
142
+ pub fn inefficient_rank < T > ( comm : & dyn Communicator , data : & [ T ] , ranking : & mut [ usize ] )
143
+ where
144
+ T : Clone + Ord + Zero ,
145
+ [ T ] : Buffer + BufferMut ,
146
+ Vec < T > : Buffer + BufferMut ,
147
+ {
129
148
assert_eq ! ( data. len( ) , ranking. len( ) ) ;
130
149
131
150
let rank = comm. rank ( ) as usize ;
132
151
let world_size = comm. size ( ) as usize ;
133
152
let root = comm. process_at_rank ( 0 ) ;
134
153
135
154
if rank == 0 {
136
- let mut recv_buffer = vec ! [ 0u64 ; data. len( ) * world_size] ;
155
+ let mut recv_buffer = vec ! [ T :: zero ( ) ; data. len( ) * world_size] ;
137
156
root. gather_into_root ( data, & mut recv_buffer) ;
138
157
let all_rankings = local_rank ( & recv_buffer) ;
139
158
root. scatter_into_root ( & all_rankings, ranking) ;
@@ -150,7 +169,12 @@ pub fn inefficient_rank(comm: &dyn Communicator, data: &[u64], ranking: &mut [u6
150
169
/// - `comm` mpi communicator
151
170
/// - `data` partial data of this process
152
171
/// - `ranking` output parameter for the ranking
153
- pub fn inefficient_rank_var ( comm : & dyn Communicator , data : & [ u64 ] , ranking : & mut [ u64 ] ) {
172
+ pub fn inefficient_rank_var < T > ( comm : & dyn Communicator , data : & [ T ] , ranking : & mut [ usize ] )
173
+ where
174
+ T : Clone + Ord + Zero ,
175
+ [ T ] : Buffer + BufferMut ,
176
+ Vec < T > : Buffer + BufferMut ,
177
+ {
154
178
assert_eq ! ( data. len( ) , ranking. len( ) ) ;
155
179
156
180
let world_size = comm. size ( ) as usize ;
@@ -168,7 +192,7 @@ pub fn inefficient_rank_var(comm: &dyn Communicator, data: &[u64], ranking: &mut
168
192
169
193
// collect data
170
194
let mut all_data_vec =
171
- vec ! [ 0u64 ; ( displs[ displs. len( ) - 1 ] + counts[ counts. len( ) - 1 ] ) as usize ] ;
195
+ vec ! [ T :: zero ( ) ; ( displs[ displs. len( ) - 1 ] + counts[ counts. len( ) - 1 ] ) as usize ] ;
172
196
let mut all_data = PartitionMut :: new ( & mut all_data_vec, counts. borrow ( ) , displs. borrow ( ) ) ;
173
197
root_process. gather_varcount_into_root ( data, & mut all_data) ;
174
198
@@ -281,10 +305,11 @@ pub fn matrix_rank(comm: &dyn Communicator, data: &[u64], ranks: &mut [u64]) {
281
305
/// They are not exhaustive and only check for obvious regressions.
282
306
#[ cfg( test) ]
283
307
mod tests {
308
+ use rusty_fork:: rusty_fork_test;
309
+
284
310
use crate :: {
285
311
inefficient_rank, inefficient_rank_var, inefficient_sort, inefficient_sort_var, matrix_rank,
286
312
} ;
287
- use rusty_fork:: rusty_fork_test;
288
313
289
314
rusty_fork_test ! {
290
315
#[ test]
@@ -323,15 +348,15 @@ mod tests {
323
348
rusty_fork_test ! {
324
349
#[ test]
325
350
fn test_inefficient_rank( ) {
326
- let data = [ 234 , 23 , 4 , 235 , 24 ] ;
327
- let mut ranking = vec![ 0u64 ; data. len( ) ] ;
351
+ let data = [ 234u64 , 23 , 4 , 235 , 24 ] ;
352
+ let mut ranking = vec![ 0usize ; data. len( ) ] ;
328
353
329
354
let universe = mpi:: initialize( ) . unwrap( ) ;
330
355
let world = universe. world( ) ;
331
356
332
357
inefficient_rank( & world, & data, & mut ranking) ;
333
358
334
- let expected = [ 3 , 1 , 0 , 4 , 2 ] ;
359
+ let expected = [ 3usize , 1 , 0 , 4 , 2 ] ;
335
360
assert_eq!( expected. len( ) , ranking. len( ) ) ;
336
361
expected
337
362
. iter( )
@@ -344,7 +369,7 @@ mod tests {
344
369
#[ test]
345
370
fn test_inefficient_rank_var_with_ties( ) {
346
371
let data = [ 1 , 1 , 4 , 5 , 24 ] ;
347
- let mut ranking = vec![ 0u64 ; data. len( ) ] ;
372
+ let mut ranking = vec![ 0usize ; data. len( ) ] ;
348
373
349
374
let universe = mpi:: initialize( ) . unwrap( ) ;
350
375
let world = universe. world( ) ;
@@ -360,7 +385,7 @@ mod tests {
360
385
#[ test]
361
386
fn test_inefficient_rank_var( ) {
362
387
let data = [ 234 , 23 , 4 , 235 , 24 ] ;
363
- let mut ranking = vec![ 0u64 ; data. len( ) ] ;
388
+ let mut ranking = vec![ 0usize ; data. len( ) ] ;
364
389
365
390
let universe = mpi:: initialize( ) . unwrap( ) ;
366
391
let world = universe. world( ) ;
@@ -379,7 +404,7 @@ mod tests {
379
404
#[ test]
380
405
fn test_inefficient_rank_with_ties( ) {
381
406
let data = [ 1 , 1 , 4 , 5 , 24 ] ;
382
- let mut ranking = vec![ 0u64 ; data. len( ) ] ;
407
+ let mut ranking = vec![ 0usize ; data. len( ) ] ;
383
408
384
409
let universe = mpi:: initialize( ) . unwrap( ) ;
385
410
let world = universe. world( ) ;
@@ -394,15 +419,15 @@ mod tests {
394
419
rusty_fork_test ! {
395
420
#[ test]
396
421
fn test_matrix_rank( ) {
397
- let data = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] ;
422
+ let data = [ 1u64 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] ;
398
423
let mut ranking = vec![ 0u64 ; data. len( ) ] ;
399
424
400
425
let universe = mpi:: initialize( ) . unwrap( ) ;
401
426
let world = universe. world( ) ;
402
427
403
428
matrix_rank( & world, & data, & mut ranking) ;
404
429
405
- let expected = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ;
430
+ let expected = [ 0u64 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ;
406
431
assert_eq!( expected. len( ) , ranking. len( ) ) ;
407
432
expected
408
433
. iter( )
0 commit comments