@@ -13,111 +13,112 @@ function backproject!(
13
13
viewidx:: Int ,
14
14
)
15
15
16
- Threads . @threads for z in 1 : plan . imgsize[ 3 ] # 1:nz
17
- thid = Threads . threadid () # thread id
18
-
16
+ # rotate image and mumap using multiple processors (adjoint)
17
+ nz = plan . imgsize[ 3 ] # prepare to loop over slices
18
+ spawner (plan . nthread, nz) do buffer_id, iz
19
19
# rotate mumap
20
- imrotate! (( @view plan . mumapr[:, :, z]),
21
- (@view plan. mumap [:, :, z ]),
22
- plan. viewangle[viewidx] ,
23
- plan. planrot[thid ],
24
- )
25
-
26
- end # COV_EXCL_LINE
20
+ imrotate! (
21
+ (@view plan. mumapr [:, :, iz ]),
22
+ ( @view plan. mumap[:, :, iz]) ,
23
+ plan. viewangle[viewidx ],
24
+ plan . planrot[buffer_id],
25
+ )
26
+ end
27
27
28
28
# adjoint of convolving img with psf and applying attenuation map
29
- Threads . @threads for y in 1 : plan. imgsize[2 ] # 1:ny
30
- thid = Threads . threadid () # thread id
29
+ ny = plan. imgsize[2 ] # prepare to loop over y planes
30
+ spawner (plan . nthread, ny) do buffer_id, iy
31
31
# account for half of the final slice thickness
32
- scale3dj! (plan. exp_mumapr[thid], plan. mumapr, y, - 0.5 )
33
- for j in 1 : y
34
- plus3dj! (plan. exp_mumapr[thid], plan. mumapr, j)
35
- end
32
+ scale3dj! (plan. exp_mumapr[buffer_id], plan. mumapr, iy, - 0.5 )
36
33
37
- broadcast! ( * , plan . exp_mumapr[thid], plan . exp_mumapr[thid], - plan . dy)
38
-
39
- broadcast! (exp, plan . exp_mumapr[thid], plan . exp_mumapr[thid])
34
+ for j in 1 : iy
35
+ plus3dj! (plan . exp_mumapr[buffer_id], plan . mumapr, j)
36
+ end
40
37
41
- fft_conv_adj! ((@view plan. imgr[:, y, :]),
42
- view,
43
- (@view plan. psfs[:, :, y, viewidx]),
44
- plan. planpsf[thid],
45
- )
38
+ broadcast! (* , plan. exp_mumapr[buffer_id], plan. exp_mumapr[buffer_id], - plan. dy)
39
+ broadcast! (exp, plan. exp_mumapr[buffer_id], plan. exp_mumapr[buffer_id])
46
40
47
- mul3dj! (plan. imgr, plan. exp_mumapr[thid], y)
48
- end # COV_EXCL_LINE
41
+ fft_conv_adj! (
42
+ (@view plan. imgr[:, iy, :]),
43
+ view,
44
+ (@view plan. psfs[:, :, iy, viewidx]),
45
+ plan. planpsf[buffer_id],
46
+ )
49
47
50
- # adjoint of rotating image
51
- Threads. @threads for z in 1 : plan. imgsize[3 ] # 1:nz
52
- thid = Threads. threadid ()
48
+ mul3dj! (plan. imgr, plan. exp_mumapr[buffer_id], iy)
49
+ end
53
50
54
- imrotate_adj! ((@view image[:, :, z]),
55
- (@view plan. imgr[:, :, z]),
56
- plan. viewangle[viewidx],
57
- plan. planrot[thid],
58
- )
59
- end # COV_EXCL_LINE
51
+ # adjoint of rotate image
52
+ spawner (plan. nthread, nz) do buffer_id, iz
53
+ imrotate_adj! (
54
+ (@view image[:, :, iz]),
55
+ (@view plan. imgr[:, :, iz]),
56
+ plan. viewangle[viewidx],
57
+ plan. planrot[buffer_id],
58
+ )
59
+ end
60
60
61
61
return image
62
62
end
63
63
64
64
65
65
"""
66
- backproject!(image, view, plan, thid , viewidx)
66
+ backproject!(image, view, plan, buffer_id , viewidx)
67
67
Backproject a single view.
68
68
"""
69
69
function backproject! (
70
70
image:: AbstractArray{<:RealU, 3} ,
71
71
view:: AbstractMatrix{<:RealU} ,
72
72
plan:: SPECTplan ,
73
- thid :: Int ,
73
+ buffer_id :: Int ,
74
74
viewidx:: Int ,
75
75
)
76
76
77
+ # rotate mumap
77
78
for z in 1 : plan. imgsize[3 ] # 1:nz
78
- # thid = Threads.threadid() # thread id
79
-
80
- # rotate mumap
81
- imrotate! ((@view plan. mumapr[thid][:, :, z]),
82
- (@view plan. mumap[:, :, z]),
83
- plan. viewangle[viewidx],
84
- plan. planrot[thid],
85
- )
79
+ imrotate! (
80
+ (@view plan. mumapr[buffer_id][:, :, z]),
81
+ (@view plan. mumap[:, :, z]),
82
+ plan. viewangle[viewidx],
83
+ plan. planrot[buffer_id],
84
+ )
86
85
87
86
end
88
87
89
88
# adjoint of convolving img with psf and applying attenuation map
90
89
for y in 1 : plan. imgsize[2 ] # 1:ny
91
- thid = Threads. threadid () # thread id
92
90
# account for half of the final slice thickness
93
- scale3dj! (plan. exp_mumapr[thid], plan. mumapr[thid], y, - 0.5 )
91
+ scale3dj! (plan. exp_mumapr[buffer_id], plan. mumapr[buffer_id], y, - 0.5 )
92
+
94
93
for j in 1 : y
95
- plus3dj! (plan. exp_mumapr[thid ], plan. mumapr[thid ], j)
94
+ plus3dj! (plan. exp_mumapr[buffer_id ], plan. mumapr[buffer_id ], j)
96
95
end
97
96
98
- broadcast! (* , plan. exp_mumapr[thid ], plan. exp_mumapr[thid ], - plan. dy)
97
+ broadcast! (* , plan. exp_mumapr[buffer_id ], plan. exp_mumapr[buffer_id ], - plan. dy)
99
98
100
- broadcast! (exp, plan. exp_mumapr[thid ], plan. exp_mumapr[thid ])
99
+ broadcast! (exp, plan. exp_mumapr[buffer_id ], plan. exp_mumapr[buffer_id ])
101
100
102
- fft_conv_adj! ((@view plan. imgr[thid][:, y, :]),
103
- view,
104
- (@view plan. psfs[:, :, y, viewidx]),
105
- plan. planpsf[thid],
106
- )
101
+ fft_conv_adj! (
102
+ (@view plan. imgr[buffer_id][:, y, :]),
103
+ view,
104
+ (@view plan. psfs[:, :, y, viewidx]),
105
+ plan. planpsf[buffer_id],
106
+ )
107
107
108
- mul3dj! (plan. imgr[thid ], plan. exp_mumapr[thid ], y)
108
+ mul3dj! (plan. imgr[buffer_id ], plan. exp_mumapr[buffer_id ], y)
109
109
end
110
110
111
111
# adjoint of rotating image
112
112
for z in 1 : plan. imgsize[3 ] # 1:nz
113
- imrotate_adj! ((@view plan. imgr[thid][:, :, z]),
114
- (@view plan. imgr[thid][:, :, z]),
115
- plan. viewangle[viewidx],
116
- plan. planrot[thid],
117
- )
113
+ imrotate_adj! (
114
+ (@view plan. imgr[buffer_id][:, :, z]),
115
+ (@view plan. imgr[buffer_id][:, :, z]),
116
+ plan. viewangle[viewidx],
117
+ plan. planrot[buffer_id],
118
+ )
118
119
end
119
120
120
- broadcast! (+ , image, image, plan. imgr[thid ])
121
+ broadcast! (+ , image, image, plan. imgr[buffer_id ])
121
122
122
123
return image
123
124
end
@@ -138,11 +139,14 @@ function backproject!(
138
139
# loop over each view index
139
140
image .= zero (plan. T) # must be initialized as zero
140
141
if plan. mode === :fast
141
- [plan. add_img[i] .= zero (plan. T) for i in 1 : plan. nthread]
142
- Threads. @threads for (i, viewidx) in collect (enumerate (index))
143
- thid = Threads. threadid ()
144
- backproject! (plan. add_img[thid], (@view views[:, :, i]), plan, thid, viewidx)
145
- end # COV_EXCL_LINE
142
+ for i in 1 : plan. nthread
143
+ plan. add_img[i] .= zero (plan. T)
144
+ end
145
+
146
+ spawner (plan. nthread, length (index)) do buffer_id, ii
147
+ viewidx = index[ii]
148
+ backproject! (plan. add_img[buffer_id], (@view views[:,:,ii]), plan, buffer_id, viewidx)
149
+ end
146
150
147
151
for i in 1 : plan. nthread
148
152
broadcast! (+ , image, image, plan. add_img[i])
@@ -187,6 +191,7 @@ function backproject(
187
191
dy:: RealU ;
188
192
interpmeth:: Symbol = :two ,
189
193
mode:: Symbol = :fast ,
194
+ # nthread::Int = Threads.nthreads(), # todo: option for plan
190
195
kwargs... ,
191
196
)
192
197
0 commit comments