Skip to content

Commit 9f9411c

Browse files
authored
Merge pull request #54 from sourceryinstitute/encapsulate-bin-array
Encapsulate bin array
2 parents 423f091 + 3355935 commit 9f9411c

File tree

5 files changed

+83
-57
lines changed

5 files changed

+83
-57
lines changed

.github/workflows/CI.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88

99
env:
1010
FC: gfortran
11-
GCC_V: 12
11+
GCC_V: 13
1212

1313
steps:
1414
- name: Checkout code
@@ -29,7 +29,7 @@ jobs:
2929
id: cache-opencoarrays
3030
uses: actions/cache@v3
3131
with:
32-
path: "OpenCoarrays-2.10.0/"
32+
path: "OpenCoarrays-2.10.1/"
3333
key: ${{ steps.time.outputs.time }}
3434

3535
- name: Install GFortran, OpenCoarrays
@@ -39,9 +39,9 @@ jobs:
3939
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_V} 100 \
4040
--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${GCC_V} \
4141
--slave /usr/bin/g++ g++ /usr/bin/g++-${GCC_V}
42-
if [ ! -d OpenCoarrays-2.10.0 ] ; then wget -P . https://github.com/sourceryinstitute/OpenCoarrays/releases/download/2.10.0/OpenCoarrays-2.10.0.tar.gz && tar -xf OpenCoarrays-2.10.0.tar.gz && cd OpenCoarrays-2.10.0 && TERM=xterm ./install.sh -y; fi
42+
if [ ! -d OpenCoarrays-2.10.1 ] ; then wget -P . https://github.com/sourceryinstitute/OpenCoarrays/releases/download/2.10.1/OpenCoarrays-2.10.1.tar.gz && tar -xf OpenCoarrays-2.10.1.tar.gz && cd OpenCoarrays-2.10.1 && TERM=xterm ./install.sh -y; fi
4343
4444
- name: Build, run, and test
4545
run: |
46-
source OpenCoarrays-2.10.0/prerequisites/installations/opencoarrays/2.10.0/setup.sh
46+
source OpenCoarrays-2.10.1/prerequisites/installations/opencoarrays/2.10.1/setup.sh
4747
fpm test --compiler caf --runner "cafrun -n 2"

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,15 @@ See the [Sourcery GitHub Pages site] for HTML documentation generated with [`for
6464

6565
Prerequisites
6666
-------------
67-
[FORD] 6.1.0 or later is required for producing HTML documentation (see
68-
"[Building the documentation]" below for instructions). The Fortran Package
69-
Manager ([fpm]) is required to build Sourcery from source. See the
70-
[fpm manifest](./fpm.toml) for the dependencies and developer dependencies,
71-
all of which [fpm] automatically downloads and builds via the `fpm` command
72-
provided in the "[Downloding, Building, and Testing]" section below.
67+
* [FORD] 6.1.0 or later is required for producing HTML documentation (see
68+
"[Building the documentation]" below for instructions).
69+
* The Fortran Package Manager ([fpm]) is required to build Sourcery from source.
70+
* GCC (`gfortran`) 13.1.0
71+
* OpenCoarrays 2.10.1 for parallel execution
72+
73+
See [fpm manifest](./fpm.toml) for the dependencies and developer dependencies,
74+
that [fpm] automatically downloads and builds via the `fpm` command provided in
75+
the "[Downloding, Building, and Testing]" section below.
7376

7477

7578
Downloding, Building, and Testing

src/sourcery/sourcery_data_partition_m.f90

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module sourcery_data_partition_m
22
!! distribute data identification numbers across images such that the number of
33
!! items differs by at most 1 between any two images.
44
use iso_fortran_env, only : real32, real64
5+
use sourcery_bin_m, only : bin_t
56
implicit none
67

78
private
@@ -10,31 +11,46 @@ module sourcery_data_partition_m
1011
type data_partition_t
1112
!! encapsulate a description of the data subset the executing image owns
1213
private
14+
type(bin_t), allocatable :: bin(:)
1315
contains
14-
procedure, nopass :: define_partitions
15-
procedure, nopass :: first
16-
procedure, nopass :: last
17-
procedure, nopass, private :: gather_real32_2D_array, gather_real64_2D_array, gather_real32_1D_array, gather_real64_1D_array
16+
procedure :: define_partitions
17+
procedure :: first
18+
procedure :: last
19+
procedure, private :: gather_real32_2D_array, gather_real64_2D_array, gather_real32_1D_array, gather_real64_1D_array
1820
generic :: gather => gather_real32_2D_array, gather_real64_2D_array, gather_real32_1D_array, gather_real64_1D_array
1921
end type
2022

23+
interface data_partition_t
24+
25+
pure module function construct(cardinality) result(data_partition)
26+
implicit none
27+
type(data_partition_t) data_partition
28+
integer, intent(in) :: cardinality
29+
end function
30+
31+
end interface
32+
2133
interface
2234

23-
module subroutine define_partitions(cardinality)
35+
pure module subroutine define_partitions(self, cardinality)
2436
!! define the range of data identification numbers owned by the executing image
37+
implicit none
38+
class(data_partition_t), intent(inout) :: self
2539
integer, intent(in) :: cardinality
2640
end subroutine
2741

28-
pure module function first(image_number) result(first_index)
42+
pure module function first(self, image_number) result(first_index)
2943
!! the result is the first identification number owned by the executing image
3044
implicit none
45+
class(data_partition_t), intent(in) :: self
3146
integer, intent(in), optional :: image_number
3247
integer first_index
3348
end function
3449

35-
pure module function last(image_number) result(last_index)
50+
pure module function last(self, image_number) result(last_index)
3651
!! the result is the last identification number owned by the executing image
3752
implicit none
53+
class(data_partition_t), intent(in) :: self
3854
integer, intent(in), optional :: image_number
3955
integer last_index
4056
end function
@@ -43,29 +59,37 @@ pure module function last(image_number) result(last_index)
4359
!! 1. Near the beginning/end of execution to amortize costs across an entire run or
4460
!! 2. Temporarily while developing/debugging code.
4561

46-
module subroutine gather_real32_1D_array( a, result_image, dim )
62+
module subroutine gather_real32_1D_array(self, a, result_image, dim )
4763
!! Gather the elements of an 1D array distributed along dimension dim onto result_image
64+
implicit none
65+
class(data_partition_t), intent(in) :: self
4866
real(real32), intent(inout) :: a(:)
4967
integer, intent(in), optional :: result_image
5068
integer, intent(in), optional :: dim
5169
end subroutine
5270

53-
module subroutine gather_real64_1D_array( a, result_image, dim )
71+
module subroutine gather_real64_1D_array(self, a, result_image, dim )
5472
!! Gather the elements of an 1D array distributed along dimension dim onto result_image
73+
implicit none
74+
class(data_partition_t), intent(in) :: self
5575
real(real64), intent(inout) :: a(:)
5676
integer, intent(in), optional :: result_image
5777
integer, intent(in), optional :: dim
5878
end subroutine
5979

60-
module subroutine gather_real32_2D_array( a, result_image, dim )
80+
module subroutine gather_real32_2D_array(self, a, result_image, dim )
6181
!! Gather the elements of an 2D array distributed along dimension dim onto result_image
82+
implicit none
83+
class(data_partition_t), intent(in) :: self
6284
real(real32), intent(inout) :: a(:,:)
6385
integer, intent(in), optional :: result_image
6486
integer, intent(in), optional :: dim
6587
end subroutine
6688

67-
module subroutine gather_real64_2D_array( a, result_image, dim )
89+
module subroutine gather_real64_2D_array(self, a, result_image, dim )
6890
!! Gather the elements of an 2D array distributed along dimension dim onto result_image
91+
implicit none
92+
class(data_partition_t), intent(in) :: self
6993
real(real64), intent(inout) :: a(:,:)
7094
integer, intent(in), optional :: result_image
7195
integer, intent(in), optional :: dim

src/sourcery/sourcery_data_partition_s.f90

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,46 @@
11
submodule(sourcery_data_partition_m) sourcery_data_partition_s
22
use assert_m, only : assert
3-
use sourcery_bin_m, only : bin_t
43
implicit none
54

65
logical, parameter :: verbose=.false.
7-
type(bin_t), allocatable :: bin(:)
86

97
contains
108

119
module procedure define_partitions
1210
integer image
13-
bin = [( bin_t(num_items=cardinality, num_bins=num_images(), bin_number=image), image=1,num_images() )]
11+
associate(ni => num_images())
12+
self%bin = [( bin_t(num_items=cardinality, num_bins=ni, bin_number=image), image=1,ni )]
13+
end associate
14+
end procedure
15+
16+
module procedure construct
17+
call data_partition%define_partitions(cardinality)
1418
end procedure
1519

1620
module procedure first
1721
integer image
1822

19-
call assert( allocated(bin), "data_partition_s(first): allocated(bin)")
23+
call assert( allocated(self%bin), "data_partition_s(first): allocated(self%bin)")
2024

2125
if (present(image_number)) then
2226
image = image_number
2327
else
2428
image = this_image()
2529
end if
26-
first_index = bin(image)%first()
30+
first_index = self%bin(image)%first()
2731
end procedure
2832

2933
module procedure last
3034
integer image
3135

32-
call assert( allocated(bin), "data_partition_s(last): allocated(bin)")
36+
call assert( allocated(self%bin), "data_partition_s(last): allocated(self%in)")
3337

3438
if (present(image_number)) then
3539
image = image_number
3640
else
3741
image = this_image()
3842
end if
39-
last_index = bin(image)%last()
43+
last_index = self%bin(image)%last()
4044
end procedure
4145

4246
module procedure gather_real32_1D_array
@@ -48,7 +52,7 @@
4852
write(6,*) 'gather_real_1D_array(): executing on image', me
4953
flush(6)
5054
end if
51-
associate( first=>first(me), last=>last(me) )
55+
associate(first=>self%first(me), last=>self%last(me))
5256
if (.not. present(result_image)) then
5357
a(1:first-1) = 0.
5458
a(last+1:) = 0.
@@ -80,7 +84,7 @@
8084
write(6,*) 'gather_real_1D_array(): executing on image', me
8185
flush(6)
8286
end if
83-
associate( first=>first(me), last=>last(me) )
87+
associate(first=>self%first(me), last=>self%last(me))
8488
if (.not. present(result_image)) then
8589
a(1:first-1) = 0.
8690
a(last+1:) = 0.
@@ -117,7 +121,7 @@
117121
write(6,*) 'gather_real32_2D_array(): executing on image', me
118122
flush(6)
119123
end if
120-
associate( first => first(me), last => last(me) )
124+
associate(first=>self%first(me), last=>self%last(me))
121125
if (.not. present(result_image)) then
122126
select case(dim_)
123127
case(1)
@@ -182,7 +186,7 @@
182186
write(6,*) 'gather_real64_2D_array(): executing on image', me
183187
flush(6)
184188
end if
185-
associate( first => first(me), last => last(me) )
189+
associate(first => self%first(me), last => self%last(me))
186190
if (.not. present(result_image)) then
187191
select case(dim_)
188192
case(1)

test/data_partition_test.f90

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,18 @@ pure function subject() result(specimen)
2626
function results() result(test_results)
2727
type(test_result_t), allocatable :: test_results(:)
2828

29-
call partition%define_partitions(cardinality=num_particles)
30-
31-
associate( me=>this_image() )
32-
associate( my_first=>partition%first(me), my_last=>partition%last(me) )
33-
test_results = [ &
34-
test_result_t("partitioning data in nearly even blocks", verify_block_partitioning()), &
35-
test_result_t("default image_number is this_image()", verify_default_image_number()), &
36-
test_result_t("partitioning all data across all images without data loss", verify_all_particles_partitioned()), &
37-
test_result_t("gathering a 1D real array onto all images", verify_all_gather_1D_real_array()), &
38-
test_result_t("gathering dimension 1 of 2D real array onto all images witout dim argument", &
39-
verify_all_gather_2D_real_array()), &
40-
test_result_t("gathering dimension 1 of 2D real array onton all images with dim argument", &
41-
verify_all_gather_2D_real_array_dim1()), &
42-
test_result_t("gathering dimension 1 of 2D real array onto result_image with dim argument", &
43-
verify_gather_2D_real_array_dim1()) &
44-
]
45-
end associate
46-
end associate
29+
test_results = [ &
30+
test_result_t("partitioning data in nearly even blocks", verify_block_partitioning()), &
31+
test_result_t("default image_number is this_image()", verify_default_image_number()), &
32+
test_result_t("partitioning all data across all images without data loss", verify_all_particles_partitioned()), &
33+
test_result_t("gathering a 1D real array onto all images", verify_all_gather_1D_real_array()), &
34+
test_result_t("gathering dimension 1 of 2D real array onto all images witout dim argument", &
35+
verify_all_gather_2D_real_array()), &
36+
test_result_t("gathering dimension 1 of 2D real array onton all images with dim argument", &
37+
verify_all_gather_2D_real_array_dim1()), &
38+
test_result_t("gathering dimension 1 of 2D real array onto result_image with dim argument", &
39+
verify_gather_2D_real_array_dim1()) &
40+
]
4741
end function
4842

4943
function verify_block_partitioning() result(test_passes)
@@ -53,7 +47,7 @@ function verify_block_partitioning() result(test_passes)
5347
logical test_passes
5448
integer my_particles
5549

56-
associate( me=>this_image() )
50+
associate( me=>this_image(), partition => data_partition_t(cardinality=num_particles))
5751
associate( my_first=>partition%first(me), my_last=>partition%last(me) )
5852
my_particles = my_last - my_first + 1
5953
associate( ni=>num_images() )
@@ -63,14 +57,15 @@ function verify_block_partitioning() result(test_passes)
6357
end associate
6458
end associate
6559
end associate
60+
6661
end function
6762

6863
function verify_default_image_number() result(test_passes)
6964
!! Verify that the first and last functions assume image_number == this_image() if image_number is not present
7065
type(data_partition_t) partition
7166
logical test_passes
7267

73-
associate( me=>this_image() )
68+
associate( me=>this_image(), partition => data_partition_t(cardinality=num_particles))
7469
test_passes = partition%first() == partition%first(me) .and.partition%last() == partition%last(me)
7570
end associate
7671
end function
@@ -82,7 +77,7 @@ function verify_all_particles_partitioned() result(test_passes)
8277
logical test_passes
8378
integer particles
8479

85-
associate(me => this_image())
80+
associate( me=>this_image(), partition => data_partition_t(cardinality=num_particles))
8681
associate( my_first=>partition%first(me), my_last=>partition%last(me) )
8782
particles = my_last - my_first + 1
8883
call co_sum(particles)
@@ -97,7 +92,7 @@ function verify_all_gather_1D_real_array() result(test_passes)
9792
real(real64) :: particle_scalar(num_particles)
9893
real(real64), parameter :: junk=-12345._real64, expected=1._real64
9994

100-
associate(me => this_image())
95+
associate( me=>this_image(), partition => data_partition_t(cardinality=num_particles))
10196
associate( first=>partition%first(me), last=>partition%last(me) )
10297
particle_scalar(first:last) = expected !! values to be gathered
10398
particle_scalar(1:first-1) = junk !! values to be overwritten by the gather
@@ -115,7 +110,7 @@ function verify_all_gather_2D_real_array() result(test_passes)
115110
real(real64) particle_vector(vec_space_dim, num_particles)
116111
real(real64), parameter :: junk=-12345._real64, expected=1._real64
117112

118-
associate(me => this_image())
113+
associate( me=>this_image(), partition => data_partition_t(cardinality=num_particles))
119114
associate( first=>partition%first(me), last=>partition%last(me) )
120115

121116
particle_vector(:, first:last) = expected !! values to be gathered
@@ -134,7 +129,7 @@ function verify_all_gather_2D_real_array_dim1() result(test_passes)
134129
real(real64) :: vector_transpose(num_particles, vec_space_dim)
135130
real(real64), parameter :: junk=-12345._real64, expected=1._real64
136131

137-
associate(me => this_image())
132+
associate( me=>this_image(), partition => data_partition_t(cardinality=num_particles))
138133
associate( first=>partition%first(me), last=>partition%last(me) )
139134

140135
vector_transpose(first:last, :) = expected !! values to be gathered
@@ -156,7 +151,7 @@ function verify_gather_2D_real_array_dim1() result(test_passes)
156151
real(real64) :: vector_transpose(num_particles, vec_space_dim)
157152
real(real64), parameter :: junk=-12345._real64, expected=1._real64
158153

159-
associate(me => this_image())
154+
associate( me=>this_image(), partition => data_partition_t(cardinality=num_particles))
160155
associate( first=>partition%first(me), last=>partition%last(me) )
161156

162157
vector_transpose(first:last, :) = expected !! values to be gathered

0 commit comments

Comments
 (0)