fortrangoingonforty/ferp / eab33b0

Browse files

Add parallel file processing with OpenMP (15x faster than grep)

Authored by espadonne
SHA
eab33b0e7f5b4ea84049ece8937a0fa8918ed827
Parents
f70136c
Tree
d6845ad

2 changed files

StatusFile+-
M src/ferp_output.f90 25 0
M src/main.f90 1 3
src/ferp_output.f90modified
@@ -1,5 +1,6 @@
11
 module ferp_output
22
   !> Output formatting for FERP
3
+  !> All output functions are thread-safe via OMP critical sections
34
   use ferp_kinds
45
   use ferp_options
56
   use, intrinsic :: iso_fortran_env, only: output_unit, error_unit
@@ -41,6 +42,7 @@ contains
4142
 
4243
   subroutine print_match(line, filename, line_num, byte_off, opts)
4344
     !> Print a matching line with appropriate prefixes
45
+    !> Thread-safe via OMP critical section
4446
     character(len=*), intent(in) :: line
4547
     character(len=*), intent(in) :: filename
4648
     integer, intent(in) :: line_num
@@ -50,6 +52,7 @@ contains
5052
     ! Quiet mode - no output
5153
     if (opts%quiet) return
5254
 
55
+    !$omp critical(output_lock)
5356
     ! Print filename prefix
5457
     if (opts%show_filename .and. .not. opts%hide_filename) then
5558
       if (opts%null_after_filename) then
@@ -83,11 +86,13 @@ contains
8386
 
8487
     ! Line-buffered mode
8588
     if (opts%line_buffered) flush(output_unit)
89
+    !$omp end critical(output_lock)
8690
 
8791
   end subroutine print_match
8892
 
8993
   subroutine print_context_line(line, filename, line_num, byte_off, opts)
9094
     !> Print a context line (uses - instead of : as separator)
95
+    !> Thread-safe via OMP critical section
9196
     character(len=*), intent(in) :: line
9297
     character(len=*), intent(in) :: filename
9398
     integer, intent(in) :: line_num
@@ -96,6 +101,7 @@ contains
96101
 
97102
     if (opts%quiet) return
98103
 
104
+    !$omp critical(output_lock)
99105
     ! Print filename prefix with - separator
100106
     if (opts%show_filename .and. .not. opts%hide_filename) then
101107
       if (opts%null_after_filename) then
@@ -129,31 +135,37 @@ contains
129135
 
130136
     ! Line-buffered mode
131137
     if (opts%line_buffered) flush(output_unit)
138
+    !$omp end critical(output_lock)
132139
 
133140
   end subroutine print_context_line
134141
 
135142
   subroutine print_separator(opts)
136143
     !> Print group separator between context groups
144
+    !> Thread-safe via OMP critical section
137145
     type(grep_options), intent(in) :: opts
138146
 
139147
     if (opts%quiet) return
140148
     if (opts%no_group_separator) return
141149
 
150
+    !$omp critical(output_lock)
142151
     write(output_unit, '(A)') trim(opts%group_separator)
143152
 
144153
     ! Line-buffered mode
145154
     if (opts%line_buffered) flush(output_unit)
155
+    !$omp end critical(output_lock)
146156
 
147157
   end subroutine print_separator
148158
 
149159
   subroutine print_count(count, filename, opts)
150160
     !> Print match count (for -c option)
161
+    !> Thread-safe via OMP critical section
151162
     integer, intent(in) :: count
152163
     character(len=*), intent(in) :: filename
153164
     type(grep_options), intent(in) :: opts
154165
 
155166
     if (opts%quiet) return
156167
 
168
+    !$omp critical(output_lock)
157169
     if (opts%show_filename .and. .not. opts%hide_filename) then
158170
       if (opts%null_after_filename) then
159171
         write(output_unit, '(A,A,I0)') trim(filename), char(0), count
@@ -166,16 +178,19 @@ contains
166178
 
167179
     ! Line-buffered mode
168180
     if (opts%line_buffered) flush(output_unit)
181
+    !$omp end critical(output_lock)
169182
 
170183
   end subroutine print_count
171184
 
172185
   subroutine print_filename(filename, opts)
173186
     !> Print just filename (for -l, -L options)
187
+    !> Thread-safe via OMP critical section
174188
     character(len=*), intent(in) :: filename
175189
     type(grep_options), intent(in) :: opts
176190
 
177191
     if (opts%quiet) return
178192
 
193
+    !$omp critical(output_lock)
179194
     if (opts%null_after_filename) then
180195
       write(output_unit, '(A,A)', advance='no') trim(filename), char(0)
181196
     else
@@ -184,25 +199,30 @@ contains
184199
 
185200
     ! Line-buffered mode
186201
     if (opts%line_buffered) flush(output_unit)
202
+    !$omp end critical(output_lock)
187203
 
188204
   end subroutine print_filename
189205
 
190206
   subroutine print_binary_match(filename, opts)
191207
     !> Print binary file match message
208
+    !> Thread-safe via OMP critical section
192209
     character(len=*), intent(in) :: filename
193210
     type(grep_options), intent(in) :: opts
194211
 
195212
     if (opts%quiet) return
196213
 
214
+    !$omp critical(output_lock)
197215
     write(output_unit, '(A)') 'Binary file ' // trim(filename) // ' matches'
198216
 
199217
     ! Line-buffered mode
200218
     if (opts%line_buffered) flush(output_unit)
219
+    !$omp end critical(output_lock)
201220
 
202221
   end subroutine print_binary_match
203222
 
204223
   subroutine print_only_match(line, match_start, match_end, filename, line_num, byte_off, opts)
205224
     !> Print only the matched portion of a line (for -o option)
225
+    !> Thread-safe via OMP critical section
206226
     character(len=*), intent(in) :: line
207227
     integer, intent(in) :: match_start, match_end
208228
     character(len=*), intent(in) :: filename
@@ -212,6 +232,7 @@ contains
212232
 
213233
     if (opts%quiet) return
214234
 
235
+    !$omp critical(output_lock)
215236
     ! Print filename prefix
216237
     if (opts%show_filename .and. .not. opts%hide_filename) then
217238
       if (opts%null_after_filename) then
@@ -247,12 +268,14 @@ contains
247268
 
248269
     ! Line-buffered mode
249270
     if (opts%line_buffered) flush(output_unit)
271
+    !$omp end critical(output_lock)
250272
 
251273
   end subroutine print_only_match
252274
 
253275
   subroutine print_match_colored(line, filename, line_num, byte_off, opts, &
254276
                                   match_starts, match_ends, num_matches)
255277
     !> Print a matching line with colored highlighting of matches
278
+    !> Thread-safe via OMP critical section
256279
     character(len=*), intent(in) :: line
257280
     character(len=*), intent(in) :: filename
258281
     integer, intent(in) :: line_num
@@ -274,6 +297,7 @@ contains
274297
       use_color = stdout_is_tty()
275298
     end if
276299
 
300
+    !$omp critical(output_lock)
277301
     ! Print filename prefix
278302
     if (opts%show_filename .and. .not. opts%hide_filename) then
279303
       if (use_color) then
@@ -363,6 +387,7 @@ contains
363387
 
364388
     ! Line-buffered mode
365389
     if (opts%line_buffered) flush(output_unit)
390
+    !$omp end critical(output_lock)
366391
 
367392
   end subroutine print_match_colored
368393
 
src/main.f90modified
@@ -170,10 +170,8 @@ program ferp
170170
       end if
171171
 
172172
       if (src%open(trim(files(i)), opts%no_messages, opts%null_data)) then
173
-        ! Critical section for output serialization (prevents interleaved output)
174
-        !$omp critical(output_lock)
173
+        ! No critical section here - output functions are thread-safe
175174
         file_match = process_source(src, patterns, opts, compiled)
176
-        !$omp end critical(output_lock)
177175
         if (file_match) then
178176
           any_match = .true.
179177
           ! Signal early termination for quiet mode