RE: [PATCH] RE: gcc parallel make check

2014-09-11 Thread VandeVondele Joost
Jakub,

 First of all, the -j2 testing shows more tests tested in gcc and libstdc++:

-# of expected passes   10133
+# of expected passes   10152

+PASS: 23_containers/set/modifiers/erase/abi_tag.cc (test for excess errors)
[...]

Not sure where the bug is, could be e.g. in i386.exp for gcc, but for
libstdc++ less likely to be there rather than in the split.

I looked into this, and believe this problem is already in current trunk, and 
not due to my patch. I.e. unmodified trunk also has these tests executed 
several times:

libstdc++-v3/testsuite/normal4/libstdc++.log.sep:PASS: 
23_containers/map/modifiers/erase/abi_tag.cc
libstdc++-v3/testsuite/normal1/libstdc++.log.sep:PASS: 
23_containers/map/modifiers/erase/abi_tag.cc

 I believe the current trunk pattern could indeed match those twice 
(Makefile.in in trunk):
  normal1) \
dirs=`cd $$srcdir; echo [ab]* de* [ep]*/*`;; \
  normal4) \
dirs=`cd $$srcdir; echo 23_*/[a-km-tw-z]*`;; \

could it be that the pattern in normal1 should have been '[ab]*/ de*/ [ep]*/*' ?


Joost




RE: [PATCH] RE: gcc parallel make check

2014-09-11 Thread VandeVondele Joost
 could it be that the pattern in normal1 should have been '[ab]*/ de*/ 
 [ep]*/*' ?

I've checked that this fixes the bug in the current trunk split. I.e. files are 
stil tested, but now only once. Consider this change added to the previously 
submitted patch.



Re: [PATCH] RE: gcc parallel make check

2014-09-11 Thread Jonathan Wakely
On 11 September 2014 07:22, VandeVondele  Joost wrote:
 Jakub,

 First of all, the -j2 testing shows more tests tested in gcc and libstdc++:

-# of expected passes   10133
+# of expected passes   10152

+PASS: 23_containers/set/modifiers/erase/abi_tag.cc (test for excess errors)
[...]

Not sure where the bug is, could be e.g. in i386.exp for gcc, but for
libstdc++ less likely to be there rather than in the split.

 I looked into this, and believe this problem is already in current trunk, and 
 not due to my patch. I.e. unmodified trunk also has these tests executed 
 several times:

 libstdc++-v3/testsuite/normal4/libstdc++.log.sep:PASS: 
 23_containers/map/modifiers/erase/abi_tag.cc
 libstdc++-v3/testsuite/normal1/libstdc++.log.sep:PASS: 
 23_containers/map/modifiers/erase/abi_tag.cc

  I believe the current trunk pattern could indeed match those twice 
 (Makefile.in in trunk):
   normal1) \
 dirs=`cd $$srcdir; echo [ab]* de* [ep]*/*`;; \
   normal4) \
 dirs=`cd $$srcdir; echo 23_*/[a-km-tw-z]*`;; \

 could it be that the pattern in normal1 should have been '[ab]*/ de*/ 
 [ep]*/*' ?

Yes, we are running these tests multiple times:

PASS: 23_containers/map/modifiers/erase/abi_tag.cc (test for excess errors)
PASS: 23_containers/multimap/modifiers/erase/abi_tag.cc (test for excess errors)
PASS: 23_containers/multiset/modifiers/erase/abi_tag.cc (test for excess errors)
PASS: 23_containers/set/modifiers/erase/abi_tag.cc (test for excess errors)
PASS: 26_numerics/complex/abi_tag.cc (test for excess errors)

I'll fix that.


RE: [PATCH] RE: gcc parallel make check

2014-09-11 Thread VandeVondele Joost

 could it be that the pattern in normal1 should have been '[ab]*/ de*/ 
 [ep]*/*' ?

Yes, we are running these tests multiple times:

PASS: 23_containers/map/modifiers/erase/abi_tag.cc (test for excess errors)
PASS: 23_containers/multimap/modifiers/erase/abi_tag.cc (test for excess 
errors)
PASS: 23_containers/multiset/modifiers/erase/abi_tag.cc (test for excess 
errors)
PASS: 23_containers/set/modifiers/erase/abi_tag.cc (test for excess errors)
PASS: 26_numerics/complex/abi_tag.cc (test for excess errors)

I'll fix that.

Actually, the proper pattern should presumably be '[ab]*/* de*/* [ep]*/*' even 
though it seems to make no difference in testing. I'll have this included in 
yet another version of the parallel make check patch (plus some further 
reschuffling as requested by Jakub), so I think there is no need for you to fix 
this now.


Re: [PATCH] RE: gcc parallel make check

2014-09-11 Thread Jonathan Wakely
On 11 September 2014 15:45, VandeVondele  Joost
joost.vandevond...@mat.ethz.ch wrote:

 could it be that the pattern in normal1 should have been '[ab]*/ de*/ 
 [ep]*/*' ?

Yes, we are running these tests multiple times:

PASS: 23_containers/map/modifiers/erase/abi_tag.cc (test for excess errors)
PASS: 23_containers/multimap/modifiers/erase/abi_tag.cc (test for excess 
errors)
PASS: 23_containers/multiset/modifiers/erase/abi_tag.cc (test for excess 
errors)
PASS: 23_containers/set/modifiers/erase/abi_tag.cc (test for excess errors)
PASS: 26_numerics/complex/abi_tag.cc (test for excess errors)

I'll fix that.

 Actually, the proper pattern should presumably be '[ab]*/* de*/* [ep]*/*' 
 even though it seems to make no difference in testing.

Yes, that's what I'm testing.

 I'll have this included in yet another version of the parallel make check 
 patch (plus some further reschuffling as requested by Jakub), so I think 
 there is no need for you to fix this now.

This can (and should) be fixed now, without waiting for some other change.


Re: [PATCH] RE: gcc parallel make check

2014-09-10 Thread Jakub Jelinek
On Tue, Sep 09, 2014 at 03:14:08PM +, VandeVondele  Joost wrote:
 Attached is a further revision of the patch, now dealing with check-c++. 
 Roughly 50% speedup here at '-j32' (18m vs 12m). For my setup 
 (--enable-languages=c,c++,fortran) I have now improved all targets called in 
 'make -j32 -k check'. The latter is now 30% faster (15m vs 20m). Note that 
 there are +- 1m fluctuations in these numbers, easily.
 
 I currently have no plans to work on other check targets before this patch is 
 committed.
 
 OK for trunk ?

So, I've tested your patch on a few years old 16way AMD,
--enable-checking=yes and with make check -j1 and make check -j2
(the former doesn't parallelize, the latter does).

First of all, the -j2 testing shows more tests tested in gcc and libstdc++:

=== gcc Summary ===
 
-# of expected passes   108100
+# of expected passes   108130
 # of unexpected failures   175
 # of unexpected successes  33
 # of expected failures 262
...
=== libstdc++ Summary ===
 
-# of expected passes   10133
+# of expected passes   10152

In gcc testsuite the difference seems to be (according to sorted PASS
lines from *.sum files):
+PASS: gcc.target/i386/vect-args.c -m3dnow -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -m3dnow -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -m3dnow -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -m3dnow  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -m3dnow  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -m3dnow  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -mmmx -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -mmmx -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -mmmx -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -mmmx  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -mmmx  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -mmmx  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse2 -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse2 -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse2 -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse2  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse2  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse2  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c -msse  (test for excess errors)
+PASS: gcc.target/i386/vect-args.c  -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c  -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c  -O (test for excess errors)
+PASS: gcc.target/i386/vect-args.c   (test for excess errors)
+PASS: gcc.target/i386/vect-args.c   (test for excess errors)
+PASS: gcc.target/i386/vect-args.c   (test for excess errors)
and in libstdc++:
+PASS: 23_containers/map/modifiers/erase/abi_tag.cc scan-assembler 
_ZNSt3mapIiiSt4lessIiESaISt4pairIKiiEEE5eraseB5cxx11ESt17_Rb_tree_iteratorIS4_E
+PASS: 23_containers/map/modifiers/erase/abi_tag.cc (test for excess errors)
+PASS: 23_containers/multimap/modifiers/erase/abi_tag.cc scan-assembler 
_ZNSt8multimapIiiSt4lessIiESaISt4pairIKiiEEE5eraseB5cxx11ESt17_Rb_tree_iteratorIS4_E
+PASS: 23_containers/multimap/modifiers/erase/abi_tag.cc (test for excess 
errors)
+PASS: 23_containers/multiset/modifiers/erase/abi_tag.cc scan-assembler 
_ZNSt8multisetIiSt4lessIiESaIiEE5eraseB5cxx11ESt23_Rb_tree_const_iteratorIiE
+PASS: 23_containers/multiset/modifiers/erase/abi_tag.cc scan-assembler 
_ZNSt8multisetIiSt4lessIiESaIiEE5eraseB5cxx11ESt23_Rb_tree_const_iteratorIiES5_
+PASS: 23_containers/multiset/modifiers/erase/abi_tag.cc (test for excess 
errors)
+PASS: 23_containers/set/modifiers/erase/abi_tag.cc scan-assembler 
_ZNSt3setIiSt4lessIiESaIiEE5eraseB5cxx11ESt23_Rb_tree_const_iteratorIiE
+PASS: 23_containers/set/modifiers/erase/abi_tag.cc scan-assembler 
_ZNSt3setIiSt4lessIiESaIiEE5eraseB5cxx11ESt23_Rb_tree_const_iteratorIiES5_
+PASS: 23_containers/set/modifiers/erase/abi_tag.cc (test for excess errors)
+PASS: 26_numerics/complex/abi_tag.cc scan-assembler 
_ZNKSt7complexIdE4imagB5cxx11Ev
+PASS: 26_numerics/complex/abi_tag.cc scan-assembler 
_ZNKSt7complexIdE4realB5cxx11Ev
+PASS: 26_numerics/complex/abi_tag.cc scan-assembler 
_ZNKSt7complexI[eg]E4imagB5cxx11Ev
+PASS: 26_numerics/complex/abi_tag.cc scan-assembler 
_ZNKSt7complexI[eg]E4realB5cxx11Ev
+PASS: 26_numerics/complex/abi_tag.cc scan-assembler 
_ZNKSt7complexIfE4imagB5cxx11Ev
+PASS: 26_numerics/complex/abi_tag.cc scan-assembler 

Re: [PATCH] RE: gcc parallel make check

2014-09-10 Thread Jakub Jelinek
On Wed, Sep 10, 2014 at 01:57:01PM +, VandeVondele  Joost wrote:
 Thanks for testing.
 
 The vect-args.c I explained earlier, and is indeed due to i386.exp hardcoding 
 those.

IMHO the best fix for that is following, use the same predicate whether to
run the vect-args.c tests or not as is used for all other tests.

Ok for trunk?

2014-09-10  Jakub Jelinek  ja...@redhat.com

* gcc.target/i386/i386.exp: Only run vect-args.c tests
if runtest_file_p says they should be run.

--- gcc/testsuite/gcc.target/i386/i386.exp.jj   2014-06-10 07:58:09.0 
+0200
+++ gcc/testsuite/gcc.target/i386/i386.exp  2014-09-10 16:09:31.572493879 
+0200
@@ -316,13 +316,16 @@ if ![info exists DEFAULT_CFLAGS] then {
 dg-init
 clearcap-init
 
+global runtests
 # Special case compilation of vect-args.c so we don't have to
 # replicate it 10 times.
-foreach type {  -mmmx -m3dnow -msse -msse2 } {
-  foreach level {  -O } {
-set flags $type $level
-verbose -log Testing vect-args, $flags 1
-dg-test $srcdir/$subdir/vect-args.c $flags 
+if [runtest_file_p $runtests $srcdir/$subdir/vect-args.c] {
+  foreach type {  -mmmx -m3dnow -msse -msse2 } {
+foreach level {  -O } {
+  set flags $type $level
+  verbose -log Testing vect-args, $flags 1
+  dg-test $srcdir/$subdir/vect-args.c $flags 
+}
   }
 }
 

Jakub


RE: [PATCH] RE: gcc parallel make check

2014-09-10 Thread VandeVondele Joost
 You mean enhancing the script to split across arbitrarily long prefixes?
 That would be great.

I've now a script that does something like that:

~/test$ find /data/vjoost/gnu/gcc_trunk/gcc/gcc/testsuite/gfortran.dg/ 
-maxdepth 1 -type f -printf %f\n | ./generate_patterns.py 500 foo
All  3947  files matched the pattern ^[0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+ 
without exception
Final  12  patterns and match count:
(^[j-z_#+-][p-z_#+-][0-9A-Za-i][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[j-z_#+-][0-9A-Za-o][0-9A-Za-m]([.][0-9A-Za-z_#+-]+)+)
  matching  469  files
(^[0-9A-Za-i][0-9A-Za-n][0-9A-Za-n][0-9A-Za-o][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^([.][0-9A-Za-z_#+-]+)+)
  matching  433  files
(^[j-z_#+-][0-9A-Za-o][n-z_#+-][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[0-9A-Za-i][0-9A-Za-n][o-z_#+-]([.][0-9A-Za-z_#+-]+)+)
  matching  400  files
(^[j-z_#+-][p-z_#+-][j-z_#+-][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[0-9A-Za-i]([.][0-9A-Za-z_#+-]+)+)
  matching  371  files
(^[0-9A-Za-i][o-z_#+-][s-z_#+-][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[0-9A-Za-i][0-9A-Za-n][0-9A-Za-n]([.][0-9A-Za-z_#+-]+)+)
  matching  323  files
(^[0-9A-Za-i][o-z_#+-][0-9A-Za-r][o-z_#+-][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[j-z_#+-][p-z_#+-]([.][0-9A-Za-z_#+-]+)+)
  matching  314  files
(^[0-9A-Za-i][o-z_#+-][0-9A-Za-r][0-9A-Za-n][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[j-z_#+-][0-9A-Za-o]([.][0-9A-Za-z_#+-]+)+)
  matching  314  files
(^[j-z_#+-][0-9A-Za-o][0-9A-Za-m][0-9A-Za-i][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[j-z_#+-]([.][0-9A-Za-z_#+-]+)+)
  matching  272  files
(^[0-9A-Za-i][0-9A-Za-n][0-9A-Za-n][p-z_#+-][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[0-9A-Za-i][o-z_#+-]([.][0-9A-Za-z_#+-]+)+)
  matching  270  files
(^[0-9A-Za-i][0-9A-Za-n][o-z_#+-][0-9A-Za-l][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[0-9A-Za-i][0-9A-Za-n]([.][0-9A-Za-z_#+-]+)+)
  matching  265  files
(^[0-9A-Za-i][0-9A-Za-n][o-z_#+-][m-z_#+-][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+|^[0-9A-Za-i][o-z_#+-][0-9A-Za-r]([.][0-9A-Za-z_#+-]+)+)
  matching  260  files
^[j-z_#+-][0-9A-Za-o][0-9A-Za-m][j-z_#+-][0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+ 
 matching  256  files

It is a set of patterns that will match any file of the form 
'^[0-9A-Za-z_#+-]*([.][0-9A-Za-z_#+-]+)+', but such that it splits a list of 
input files roughly in equal chunks (e.g. between 500 and 500/2 in this 
example), even if files have long overlapping prefixes. However, I'm unsure 
if/how this can be integrated, i.e. what precisely is allowed for testsuite 
filenames, and if this regexp format can be employed in gcc makefiles / tcl / 
expect harness, suggestions/help appreciated.





RE: [PATCH] RE: gcc parallel make check

2014-09-09 Thread VandeVondele Joost
Attached is an extended version of the patch, it brings a 100% improvement in 
make -j32 -k check-gcc (down from 20min to 10min) by modification of 
check_gcc_parallelize.

It includes one non-trivial part, namely a split of the target exps. They are 
now all split using a common choice (based on i386), which I believe is 
reasonable as it is the target with most tests, and the patterns will be 
somewhat similar for other targets (e.g. split of p(rxxx)). The implementation 
of this in the makefile uses an odd looking technique to substitute spaces with 
commas in a variable, if this can be done more elegantly, I'm happy to make the 
change.

Bootstrap and testing revealed one issue, i386.exp hard-codes a loop for the 
testcase 'vect-args.c' in order to test 10 different combinations of options. 
With the current split (i.e. target x4) this test will thus be executed 4 
times. There are two easy options

1) keep the current setup, overhead is small
2) keep the .exp file simple and just replicate this test 10x 

I've selected 1), but I can update a patch with 2). Ideally dg-options in the 
testcase file itself could be repeated, but I haven't found an example of this. 

The script now includes sorting and compression of the ranges, and an 
additional sanity check on the input, i.e. that file names start with 
[0-9A-Za-z]. Some (few) files seem to start with _ or # (in ./gcc.dg/cpp/).

I'll follow up with a separate patch to improve check_g++_parallelize.

Full 'make -j k32 check' is now dominated by libstdc++ testing, which contains 
single goals that run ~1100s (e.g. regex related tests). These uses a slightly 
different syntax (see gcc/libstdc++-v3/testsuite/Makefile.am) and I'm not yet 
sure how to deal with the .am files.

current patch OK for trunk ?

Joost



patch-speedup-checkfortran-v05.CL
Description: patch-speedup-checkfortran-v05.CL
Index: contrib/generate_tcl_patterns.sh
===
--- contrib/generate_tcl_patterns.sh	(revision 0)
+++ contrib/generate_tcl_patterns.sh	(revision 0)
@@ -0,0 +1,114 @@
+#! /bin/sh
+
+#
+# based on a list of filenames as input, starting with [0-9A-Za-z],
+# generate regexps that match subsets trying to not exceed a
+# 'maxcount' parameter. Most useful to generate the
+# check_LANG_parallelize assignments needed to split
+# testsuite directories, defining prefix appropriately.
+#
+# Example usage:
+#   cd gcc/gcc/testsuite/gfortran.dg
+#   ls -1 | ../../../contrib/generate_tcl_patterns.sh 300 dg.exp=gfortran.dg/
+#
+# the first parameter is the maximum number of files.
+# the second parameter the prefix used for printing.
+#
+
+# Copyright (C) 2014 Free Software Foundation
+# Contributed by Joost VandeVondele joost.vandevond...@mat.ethz.ch
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING.  If not, write to
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+gawk -v maxcount=$1 -v prefix=$2 '
+BEGIN{
+  # list of allowed starting chars for a file name in a dir to split
+  achars=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+  ranget=112233
+}
+{
+  if (index(achars,substr($1,1,1))==0){
+ print file :  $1  does not start with an allowed character.
+ _assert_exit = 1
+ exit 1
+  }
+  nfiles++ ; files[nfiles]=$1
+}
+END{
+  if (_assert_exit) exit 1
+  for(i=1; i=length(achars); i++) count[substr(achars,i,1)]=0
+  for(i=1; i=nfiles; i++) {
+ if (length(files[i]0)) { count[substr(files[i],1,1)]++ }
+  };
+  asort(count,ordered)
+  countsingle=0
+  groups=0
+  label=
+  for(i=length(achars);i=1;i--) {
+countsingle=countsingle+ordered[i] 
+for(j=1;j=length(achars);j++) {
+   if(count[substr(achars,j,1)]==ordered[i]) found=substr(achars,j,1)
+}
+count[found]=-1
+label=label found
+if(i==1) { val=maxcount+1 } else { val=ordered[i-1] }
+if(countsingle+valmaxcount) {
+  subset[label]=countsingle
+  print Adding label: , label, matching files: countsingle
+  groups++
+  countsingle=0
+  label=
+}
+  }
+  print patterns:
+  asort(subset,ordered)
+  for(i=groups;i=1;i--) {
+for(j in subset){
+  if(subset[j]==ordered[i]) found=j
+}
+subset[found]=-1
+if (length(found)==1) {
+   printf(%s%s* \\\n,prefix,found)
+} else {
+   sortandcompress()
+   

Re: [PATCH] RE: gcc parallel make check

2014-09-09 Thread Yury Gribov

On 09/09/2014 10:51 AM, VandeVondele Joost wrote:
 Attached is an extended version of the patch,
 it brings a 100% improvement in make -j32 -k check-gcc

First of all, many thanks for working on this.

+#   ls -1 | ../../../contrib/generate_tcl_patterns.sh 300 
dg.exp=gfortran.dg/


How does this work with subdirectories? Can we replace ls with find?

-check_p_numbers=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+check_p_numbers=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
+   21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

$(shell seq 1 40) ?

+  if (_assert_exit) exit 1

Haven't you already exited above?

 A second part of the patch is a new file 
'contrib/generate_tcl_patterns.sh'

 which generates the needed regexp

Can we provide a Makefile target to automatically update Makefile.in?

-Y



Re: [PATCH] RE: gcc parallel make check

2014-09-09 Thread Jakub Jelinek
On Tue, Sep 09, 2014 at 02:02:18PM +0400, Yury Gribov wrote:
 On 09/09/2014 10:51 AM, VandeVondele Joost wrote:
  Attached is an extended version of the patch,
  it brings a 100% improvement in make -j32 -k check-gcc
 
 First of all, many thanks for working on this.
 
 +#   ls -1 | ../../../contrib/generate_tcl_patterns.sh 300
 dg.exp=gfortran.dg/
 
 How does this work with subdirectories? Can we replace ls with find?

Generally, if the argument to *.exp doesn't contain a particular
subdirectory, then the wildcard is taken against basenames of the tests.

 -check_p_numbers=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 +check_p_numbers=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
 
 $(shell seq 1 40) ?

Would that be sufficiently portable to weirdo hosts (M$Win, Darwin, ...)?
We require GNU make, so if it can be written in GNU make text functions,
fine, otherwise it is better to keep as is.
 
 +  if (_assert_exit) exit 1
 
 Haven't you already exited above?
 
  A second part of the patch is a new file
 'contrib/generate_tcl_patterns.sh'
  which generates the needed regexp
 
 Can we provide a Makefile target to automatically update Makefile.in?

No.  As I wrote earlier, splitting on filenames and test counts only is only
very rough split, all the splits really need to be backed out by real timing
data from popular targets.  Also, I'm afraid of some tests being left out
unintentionally (e.g. the wildcards created at some point, then a new test
is added with a weird starting character that hasn't been used before and
suddenly it will not be tested with make -j?).

Jakub


RE: [PATCH] RE: gcc parallel make check

2014-09-09 Thread VandeVondele Joost
 +#   ls -1 | ../../../contrib/generate_tcl_patterns.sh 300
 dg.exp=gfortran.dg/
 
 How does this work with subdirectories? Can we replace ls with find?

The input to the script is general, you can use this to your advantage. For 
example, I've been using:

 ls -1 g++.*/* | cut -c5- | ../../../contrib/generate_tcl_patterns.sh 700 
old-deja.exp=g++.old-deja/g++.

to split at a deeper level or

find . -name [0-9A-Za-z]* -type f -printf %f\n | 
../../../../contrib/generate_tcl_patterns.sh 300 dg-torture.exp=torture/

to collect statistics also from subdirs.

 +  if (_assert_exit) exit 1

 Haven't you already exited above?

yes, but the END{} block in awk is nevertheless executed, unless protected as 
above.

RE: [PATCH] RE: gcc parallel make check

2014-09-09 Thread VandeVondele Joost
 No.  As I wrote earlier, splitting on filenames and test counts only is only
 very rough split, all the splits really need to be backed out by real timing
 data from popular targets.  

I'm actually doing quite some testing trying to get a reasonable balance, 
checking 'completed in' in all *.log.sep files. However, it is important that 
the procedure is semi-automatic, otherwise few people will be interested in 
doing so. Furthermore, for parallel performance, it is not so important that 
times are distributed evenly (it is anyway unlikely the number of goals is 
exactly divided by N of -jN), but rather that the goals are ordered (executed) 
from slow to fast (similar to omp schedule guided). Most of the real 
bottlenecks are single letter patterns (e.g. p* since pr is such a common 
filename), and this is ultimately limiting.

In the project (CP2K) I'm working on, we also parallelize testing over 
directories, but we keep a list of approximate runtimes per directory, and keep 
that (global) list sorted. Testing follows that list. As a result, we have near 
perfect parallel speedup, despite (or because) timings per directory ranging 
from a few 100s to 1s. 

 Also, I'm afraid of some tests being left out
 unintentionally (e.g. the wildcards created at some point, then a new test
 is added with a weird starting character that hasn't been used before and
 suddenly it will not be tested with make -j?).

I agree this is an issue, partially addressed by not having to write patterns 
by hand anymore (i.e. a script does this), and by having the script check its 
input. There are something like 10 testnames that do not fall in [0-9A-Za-z], 
as mentioned in a previous email.


Re: [PATCH] RE: gcc parallel make check

2014-09-09 Thread Jakub Jelinek
On Tue, Sep 09, 2014 at 10:57:09AM +, VandeVondele  Joost wrote:
  No.  As I wrote earlier, splitting on filenames and test counts only is only
  very rough split, all the splits really need to be backed out by real timing
  data from popular targets.  
 
 Furthermore, for parallel performance, it is not
 so important that times are distributed evenly (it is anyway unlikely the
 number of goals is exactly divided by N of -jN), but rather that the goals
 are ordered (executed) from slow to fast (similar to omp schedule guided). 
 Most of the real bottlenecks are single letter patterns (e.g.  p* since
 pr is such a common filename), and this is ultimately limiting.

I disagree.  If e.g. in gcc.dg/ more than a third of testcases are pr*.c,
then running dg.exp=p* in one job and dg.exp=a* in another one etc. is
simply a bad idea, the pr*.c should be split more and some other letters
just be done together.

Even that can be done semi-automatically.

If you get whitespace right, one can provide multiple different wildcards to
a single *.exp file, e.g.
make check-gcc RUNTESTFLAGS=dg.exp='p[0-9A-Za-qs-z]* pr[9A-Za-z]*' should
cover all tests starting with p other than pr[0-8]*.c (where you could split
say pr[0-2]* into another job, pr[3-5]* into another and pr[6-8]* into
another.

The fact that some check-gcc or check-gfortran test job is early in the list
doesn't mean it will be started early, you need to consider also all other
potentially long jobs like check-g++, check-target-libgomp,
check-target-libstdc++-v3 etc.

Jakub


RE: [PATCH] RE: gcc parallel make check

2014-09-09 Thread VandeVondele Joost
 If you get whitespace right, one can provide multiple different wildcards to
 a single *.exp file, e.g.
 make check-gcc RUNTESTFLAGS=dg.exp='p[0-9A-Za-qs-z]* pr[9A-Za-z]*' should
 cover all tests starting with p other than pr[0-8]*.c (where you could split
 say pr[0-2]* into another job, pr[3-5]* into another and pr[6-8]* into
 another.

I think this confirms that it becomes very delicate to try and write these more 
complex patterns. The above would miss p_test.c, p-1.c, etc ? 

For other classes of files the difference is even further down the filename 
(e.g. using dates as in 20020508-3.c going from 2000 to 2014, or avx*), making 
the automatic generation of the patterns more complicated.

I certainly don't want to claim that the patch I have now is perfect, it is 
rather an incremental improvement on the current setup.






Re: [PATCH] RE: gcc parallel make check

2014-09-09 Thread Yury Gribov

On 09/09/2014 06:14 PM, VandeVondele Joost wrote:

I certainly don't want to claim that the patch I have now is perfect,
it is rather an incremental improvement on the current setup.


I'd second this. Writing patterns manually seems rather inefficient and 
error-prone
(not undoable of course but unnecessarily complicated). And with current 
(crippled)

version Joost already got 100% test time improvement.

-Y



Re: [PATCH] RE: gcc parallel make check

2014-09-09 Thread Jakub Jelinek
On Tue, Sep 09, 2014 at 06:27:10PM +0400, Yury Gribov wrote:
 On 09/09/2014 06:14 PM, VandeVondele Joost wrote:
 I certainly don't want to claim that the patch I have now is perfect,
 it is rather an incremental improvement on the current setup.
 
 I'd second this. Writing patterns manually seems rather inefficient and
 error-prone
 (not undoable of course but unnecessarily complicated). And with current
 (crippled)
 version Joost already got 100% test time improvement.

But if there are jobs that just take 1s to complete, then clearly it doesn't
make sense to split them off as separate job.  I think we don't need 100%
even split, but at least roughly is highly desirable.

Jakub


Re: [PATCH] RE: gcc parallel make check

2014-09-09 Thread Yury Gribov

On 09/09/2014 06:33 PM, Jakub Jelinek wrote:

On Tue, Sep 09, 2014 at 06:27:10PM +0400, Yury Gribov wrote:

On 09/09/2014 06:14 PM, VandeVondele Joost wrote:

I certainly don't want to claim that the patch I have now is perfect,
it is rather an incremental improvement on the current setup.


I'd second this. Writing patterns manually seems rather inefficient and
error-prone
(not undoable of course but unnecessarily complicated). And with current
(crippled)
version Joost already got 100% test time improvement.


But if there are jobs that just take 1s to complete, then clearly it doesn't
make sense to split them off as separate job.  I think we don't need 100%
even split, but at least roughly is highly desirable.


You mean enhancing the script to split across arbitrarily long prefixes?
That would be great.

-Y


RE: [PATCH] RE: gcc parallel make check

2014-09-09 Thread VandeVondele Joost
Now with gzipped figure.. why do these bounce ?

 But if there are jobs that just take 1s to complete, then clearly it doesn't
 make sense to split them off as separate job.  I think we don't need 100%
 even split, but at least roughly is highly desirable.

Let me add some data, attached is a graph (logscale y) showing the runtime of 
tests before and after my changes (including a new patch for c++). There is 
virtually no change for tests running shorter than 50s, only slowly running 
tests have been split.

Now, there are only very few slow tests remaining:

gcc_trunk/obj.new find . -name *.log | xargs grep  completed in  | sort -n 
-k 5 | tail -n 10
./gcc/testsuite/gcc/gcc.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/gcc/testsuite/gcc.dg/torture/dg-torture.exp 
completed in 521 seconds
./x86_64-unknown-linux-gnu/libstdc++-v3/testsuite/libstdc++.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
 completed in 530 seconds
./x86_64-unknown-linux-gnu/libstdc++-v3/testsuite/libstdc++.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
 completed in 553 seconds
./x86_64-unknown-linux-gnu/libgomp/testsuite/libgomp.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/libgomp/testsuite/libgomp.fortran/fortran.exp 
completed in 561 seconds
./gcc/testsuite/gcc/gcc.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/gcc/testsuite/gcc.c-torture/compile/compile.exp 
completed in 625 seconds
./x86_64-unknown-linux-gnu/libstdc++-v3/testsuite/libstdc++.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
 completed in 683 seconds
./gcc/testsuite/g++/g++.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/gcc/testsuite/g++.dg/dg.exp completed in 702 
seconds
./x86_64-unknown-linux-gnu/libstdc++-v3/testsuite/libstdc++.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
 completed in 726 seconds
./gcc/testsuite/gcc/gcc.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/gcc/testsuite/gcc.c-torture/execute/execute.exp 
completed in 752 seconds
./x86_64-unknown-linux-gnu/libstdc++-v3/testsuite/libstdc++.log:testcase 
/data/vjoost/gnu/gcc_trunk/gcc/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
 completed in 904 seconds

They, of course, limit the ultimate speedup.

timings.png.gz
Description: timings.png.gz


RE: [PATCH] RE: gcc parallel make check

2014-09-09 Thread VandeVondele Joost
Attached is a further revision of the patch, now dealing with check-c++. 
Roughly 50% speedup here at '-j32' (18m vs 12m). For my setup 
(--enable-languages=c,c++,fortran) I have now improved all targets called in 
'make -j32 -k check'. The latter is now 30% faster (15m vs 20m). Note that 
there are +- 1m fluctuations in these numbers, easily.

I currently have no plans to work on other check targets before this patch is 
committed.

OK for trunk ?

Joost







contrib/ChangeLog

2014-09-09  Joost VandeVondele  vond...@gcc.gnu.org

* generate_tcl_patterns.sh: New file.

gcc/fortran/ChangeLog

2014-09-09  Joost VandeVondele  vond...@gcc.gnu.org

* Make-lang.in (check_gfortran_parallelize): Improved parallelism.

gcc/Changelog

2014-09-09  Joost VandeVondele  vond...@gcc.gnu.org

* Makefile.in (check_gcc_parallelize): Improved parallelism.
(check_p_numbers): Increase maximum value.
(dg_target_exps): Mention targets as separate words only.
(null,space,comma,dg_target_exps_p1,dg_target_exps_p2,
dg_target_exps_p3,dg_target_exps_p4): New variables.

gcc/cp/ChangeLog

2014-09-09  Joost VandeVondele  vond...@gcc.gnu.org

* Make-lang.in (check_g++_parallelize): Improved parallelism.

libstdc++-v3/ChangeLog

2014-09-09  Joost VandeVondele  vond...@gcc.gnu.org

* testsuite/Makefile.am (check_DEJAGNU_normal_targets): Add
check-DEJAGNUnormal[11-15].
(check-DEJAGNU): Split into 15 jobs for parallel testing.
* testsuite/Makefile.in: Regenerated.
Index: libstdc++-v3/testsuite/Makefile.am
===
--- libstdc++-v3/testsuite/Makefile.am	(revision 215017)
+++ libstdc++-v3/testsuite/Makefile.am	(working copy)
@@ -101,7 +101,7 @@ new-abi-baseline:
 	@test ! -f $*/site.exp || mv $*/site.exp $*/site.bak
 	@mv $*/site.exp.tmp $*/site.exp
 
-check_DEJAGNU_normal_targets = $(patsubst %,check-DEJAGNUnormal%,0 1 2 3 4 5 6 7 8 9 10)
+check_DEJAGNU_normal_targets = $(patsubst %,check-DEJAGNUnormal%,0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
 $(check_DEJAGNU_normal_targets): check-DEJAGNUnormal%: normal%/site.exp
 
 # Run the testsuite in normal mode.
@@ -111,7 +111,7 @@ check-DEJAGNU $(check_DEJAGNU_normal_tar
 	if [ -z $*$(filter-out --target_board=%, $(RUNTESTFLAGS)) ] \
 	 [ $(filter -j, $(MFLAGS)) = -j ]; then \
 	  $(MAKE) $(AM_MAKEFLAGS) $(check_DEJAGNU_normal_targets); \
-	  for idx in 0 1 2 3 4 5 6 7 8 9 10; do \
+	  for idx in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do \
 	mv -f normal$$idx/libstdc++.sum normal$$idx/libstdc++.sum.sep; \
 	mv -f normal$$idx/libstdc++.log normal$$idx/libstdc++.log.sep; \
 	  done; \
@@ -138,25 +138,35 @@ check-DEJAGNU $(check_DEJAGNU_normal_tar
 	fi; \
 	dirs=`cd $$srcdir; echo [013-9][0-9]_*/*`;; \
 	  normal1) \
-	dirs=`cd $$srcdir; echo [ab]* de* [ep]*/*`;; \
+	dirs=`cd $$srcdir; echo e*/*`;; \
 	  normal2) \
-	dirs=`cd $$srcdir; echo 2[01]_*/*`;; \
+	dirs=`cd $$srcdir; echo 28_*/a*`;; \
 	  normal3) \
-	dirs=`cd $$srcdir; echo 22_*/*`;; \
+	dirs=`cd $$srcdir; echo 23_*/[lu]*`;; \
 	  normal4) \
-	dirs=`cd $$srcdir; echo 23_*/[a-km-tw-z]*`;; \
+	dirs=`cd $$srcdir; echo 2[459]_*/*`;; \
 	  normal5) \
-	dirs=`cd $$srcdir; echo 23_*/[luv]*`;; \
+	dirs=`cd $$srcdir; echo 2[01]_*/*`;; \
 	  normal6) \
-	dirs=`cd $$srcdir; echo 2[459]_*/*`;; \
+	dirs=`cd $$srcdir; echo 23_*/[m-tw-z]*`;; \
 	  normal7) \
-	dirs=`cd $$srcdir; echo 26_*/* 28_*/[c-z]*`;; \
+	dirs=`cd $$srcdir; echo 26_*/*`;; \
 	  normal8) \
 	dirs=`cd $$srcdir; echo 27_*/*`;; \
 	  normal9) \
-	dirs=`cd $$srcdir; echo 28_*/[ab]*`;; \
+	dirs=`cd $$srcdir; echo 22_*/*`;; \
 	  normal10) \
 	dirs=`cd $$srcdir; echo t*/*`;; \
+	  normal11) \
+	dirs=`cd $$srcdir; echo 28_*/b*`;; \
+	  normal12) \
+	dirs=`cd $$srcdir; echo 28_*/[c-z]*`;; \
+	  normal13) \
+	dirs=`cd $$srcdir; echo de* p*/*`;; \
+	  normal14) \
+	dirs=`cd $$srcdir; echo [ab]* 23_*/v*`;; \
+	  normal15) \
+	dirs=`cd $$srcdir; echo 23_*/[a-k]*`;; \
 	esac; \
 	if [ -n $* ]; then cd $*; fi; \
 	if $(SHELL) -c $$runtest --version  /dev/null 21; then \
Index: libstdc++-v3/testsuite/Makefile.in
===
--- libstdc++-v3/testsuite/Makefile.in	(revision 215017)
+++ libstdc++-v3/testsuite/Makefile.in	(working copy)
@@ -301,7 +301,7 @@ lists_of_files = \
 
 extract_symvers = $(glibcxx_builddir)/scripts/extract_symvers
 baseline_subdir := $(shell $(CXX) $(baseline_subdir_switch))
-check_DEJAGNU_normal_targets = $(patsubst %,check-DEJAGNUnormal%,0 1 2 3 4 5 6 7 8 9 10)
+check_DEJAGNU_normal_targets = $(patsubst %,check-DEJAGNUnormal%,0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
 
 # Runs the testsuite, but in compile only mode.
 # Can be used to test sources with non-GNU FE's at various warning
@@ -562,7 +562,7 @@ check-DEJAGNU $(check_DEJAGNU_normal_tar
 	if [ -z 

RE: [PATCH] RE: gcc parallel make check

2014-09-05 Thread VandeVondele Joost
  Please sort the letters (LC_ALL=C sort) and where consecutive, use ranges.
  Thus \[0-9A-Zhjqvx-z\]*

OK, works fine with the attached patch, and looks cleaner in Make-lang.in.

Now, with the proper email address for gcc-patches... I wonder how many time 
I'll be punished for typos.

unmodified CL.

Joost



Index: contrib/generate_tcl_patterns.sh
===
--- contrib/generate_tcl_patterns.sh	(revision 0)
+++ contrib/generate_tcl_patterns.sh	(revision 0)
@@ -0,0 +1,108 @@
+#! /bin/sh
+
+#
+# based on a list of filenames as input,
+# generate regexps that match subsets trying to not exceed a
+# 'maxcount' parameter. Most useful to generate the
+# check_LANG_parallelize assignments needed to split
+# testsuite directories, defining prefix appropriately.
+#
+# Example usage:
+#   cd gcc/gcc/testsuite/gfortran.dg
+#   ls -1 | ../../../contrib/generate_tcl_patterns.sh 300 dg.exp=gfortran.dg/
+#
+# the first parameter is the maximum number of files.
+# the second parameter the prefix used for printing.
+#
+
+# Copyright (C) 2014 Free Software Foundation
+# Contributed by Joost VandeVondele joost.vandevond...@mat.ethz.ch
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING.  If not, write to
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+gawk -v maxcount=$1 -v prefix=$2 '
+BEGIN{
+  # list of allowed starting chars for a file name in a dir to split
+  achars=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+  ranget=112233
+}
+{
+  nfiles++ ; files[nfiles]=$1
+}
+END{
+  for(i=1; i=length(achars); i++) count[substr(achars,i,1)]=0
+  for(i=1; i=nfiles; i++) {
+ if (length(files[i]0)) { count[substr(files[i],1,1)]++ }
+  };
+  asort(count,ordered)
+  countsingle=0
+  groups=0
+  label=
+  for(i=length(achars);i=1;i--) {
+countsingle=countsingle+ordered[i] 
+for(j=1;j=length(achars);j++) {
+   if(count[substr(achars,j,1)]==ordered[i]) found=substr(achars,j,1)
+}
+count[found]=-1
+label=label found
+if(i==1) { val=maxcount+1 } else { val=ordered[i-1] }
+if(countsingle+valmaxcount) {
+  subset[label]=countsingle
+  print Adding label: , label, matching files: countsingle
+  groups++
+  countsingle=0
+  label=
+}
+  }
+  print patterns:
+  asort(subset,ordered)
+  for(i=groups;i=1;i--) {
+for(j in subset){
+  if(subset[j]==ordered[i]) found=j
+}
+subset[found]=-1
+if (length(found)==1) {
+   printf(%s%s* \\\n,prefix,found)
+} else {
+   sortandcompress()
+   printf(%s\\[%s\\]* \\\n,prefix,found)
+}
+  }
+}
+function sortandcompress(i,n,tmp,bestj)
+{
+  n=length(found)
+  for(i=1; i=n; i++) tmp[i]=substr(found,i,1) 
+  asort(tmp)
+  for(i=1;i=n;i++){
+ipos=index(achars,tmp[i])
+for(j=i;j=n;j++){
+  jpos=index(achars,tmp[j])
+  if (jpos-ipos==j-i  substr(ranget,ipos,1)==substr(ranget,jpos,1)) bestj=j
+}
+if (bestj-i3) {
+  tmp[i+1]=- 
+  for(j=i+2;jbestj;j++) tmp[j]= 
+}
+i=bestj 
+  }
+  found=
+  for(i=1; i=n; i++) found=found tmp[i]
+  gsub(/ /,,found)
+}
+'
Index: gcc/fortran/Make-lang.in
===
--- gcc/fortran/Make-lang.in	(revision 214949)
+++ gcc/fortran/Make-lang.in	(working copy)
@@ -168,12 +168,22 @@ check-fortran-subtargets : check-gfortra
 lang_checks += check-gfortran
 lang_checks_parallelized += check-gfortran
 # For description see comment above check_gcc_parallelize in gcc/Makefile.in.
-check_gfortran_parallelize = dg.exp=gfortran.dg/\[adAD\]* \
-			 dg.exp=gfortran.dg/\[bcBC\]* \
-			 dg.exp=gfortran.dg/\[nopNOP\]* \
-			 dg.exp=gfortran.dg/\[isuvISUV\]* \
-			 dg.exp=gfortran.dg/\[efhkqrxzEFHKQRXZ\]* \
-			 dg.exp=gfortran.dg/\[0-9gjlmtwyGJLMTWY\]*
+check_gfortran_parallelize = execute.exp \
+			dg.exp=gfortran.dg/p* \
+			dg.exp=gfortran.dg/c* \
+			dg.exp=gfortran.dg/a* \
+			dg.exp=gfortran.dg/i* \
+			dg.exp=gfortran.dg/\[glow\]* \
+			dg.exp=gfortran.dg/\[mu\]* \
+			dg.exp=gfortran.dg/d* \
+			dg.exp=gfortran.dg/s* \
+			dg.exp=gfortran.dg/b* \
+			dg.exp=gfortran.dg/t* \
+			dg.exp=gfortran.dg/f* \
+			dg.exp=gfortran.dg/e* \
+			dg.exp=gfortran.dg/r* \
+			dg.exp=gfortran.dg/n* \
+			dg.exp=gfortran.dg/\[0-9A-Zhjkqvxyz\]*
 
 # GFORTRAN