[mpich2-commits] r6692 - in mpich2/trunk: maint src/util/param

goodell at mcs.anl.gov goodell at mcs.anl.gov
Thu May 20 22:34:24 CDT 2010


Author: goodell
Date: 2010-05-20 22:34:24 -0500 (Thu, 20 May 2010)
New Revision: 6692

Added:
   mpich2/trunk/maint/genparams
   mpich2/trunk/src/util/param/params.yml
Log:
new parameter handling script and config file

Added: mpich2/trunk/maint/genparams
===================================================================
--- mpich2/trunk/maint/genparams	                        (rev 0)
+++ mpich2/trunk/maint/genparams	2010-05-21 03:34:24 UTC (rev 6692)
@@ -0,0 +1,419 @@
+#!/usr/bin/env perl
+#
+# (C) 2010 by Argonne National Laboratory.
+#     See COPYRIGHT in top-level directory.
+#
+
+# script TODO:
+# - generate initialization function to read vals from env vars
+# - deal with string escaping in generated C strings
+# - add support for "range" types (see MPL_env2range)
+# - sort/collate paramters by name/category
+
+use strict;
+use warnings;
+
+# help perl find the YAML parsing module
+use lib 'maint/local_perl/lib';
+
+use YAML::Tiny qw();
+use File::Basename qw(basename);
+use Data::Dumper;
+use Getopt::Long;
+
+# I'm pretty sure this is a standard lib module across all perl5
+# installs, but we can work around this easily if that doesn't turn out
+# to be true. [goodell@ 2010-04-26]
+use Digest::MD5 qw();
+
+##################################################
+
+# set true to enable debug output
+my $debug = 0;
+
+# namespace prefix for variable and type names
+my $ns = "MPIR_Param";
+
+# parameter description file
+my $param_file = "src/util/param/params.yml";
+
+# output source files
+my $header_file = "src/include/mpich_param_vals.h";
+my $c_file      = "src/util/param/param_vals.c";
+
+GetOptions(
+    "help!"       => \&print_usage_and_exit,
+    "debug!"      => \$debug,
+    "namespace=s" => \$ns,
+    "param-file"  => \$param_file,
+    "header=s"    => \$header_file,
+    "c-file=s"    => \$c_file,
+) or die "unable to parse options, stopped";
+
+sub print_usage_and_exit {
+    print <<EOT;
+Usage: $0 [OPTIONS]
+
+Supported options:
+
+    --help            - this output
+    --debug           - enable some debugging output
+    --namespace=STR   - use STR as variable/type prefix in generated code
+    --param-file=FILE - use FILE as input describing parameters
+
+EOT
+    exit 1;
+}
+
+my $run_timestamp = localtime;
+my $uc_ns = uc($ns);
+
+########################################################################
+# read the config file and turn it into a perl hash/array object
+
+# NOTE: if multiple configuration files are supported in the future,
+# this is the place that should be modified to read them all in and
+# merge them into a single consistent configuration object
+
+my $yaml = YAML::Tiny->new();
+my $params = ($yaml->read($param_file))->[0]; # [0] is for the first document
+print Dumper($params)."\n" if $debug;
+die "not a HASH, stopped" unless ref($params) eq "HASH";
+
+########################################################################
+# validate the config file
+
+# only simple checks for now, just make sure that all categories
+# referenced by parameters actually exist
+my %cat_hash = (map { ($_->{name} => 1) } @{$params->{categories}});
+foreach my $p (@{$params->{parameters}}) {
+    unless (exists $cat_hash{$p->{category}}) {
+        warn "category '".$p->{category}."' referenced by '".$p->{name}."' was not found";
+    }
+}
+
+########################################################################
+# setup output files
+open(PARAM_HDR, '>', $header_file);
+open(PARAM_C,   '>', $c_file);
+
+my $hdr_guard = header_to_incl_guard($header_file);
+my $param_file_md5 = md5sum($param_file);
+
+print PARAM_HDR <<EOT;
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *  (C) 2010 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+/* automatically generated
+ *   by:   $0
+ *   on:   $run_timestamp
+ *   from: $param_file (md5sum $param_file_md5)
+ *
+ * DO NOT EDIT!!!
+ */
+
+#if !defined($hdr_guard)
+#define $hdr_guard
+
+EOT
+
+print PARAM_C <<EOT;
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *  (C) 2010 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+/* automatically generated
+ *   by:   $0
+ *   at:   $run_timestamp
+ *   from: $param_file (md5sum $param_file_md5)
+ *
+ * DO NOT EDIT!!!
+ */
+
+#include "mpiimpl.h"
+
+EOT
+
+########################################################################
+# actually process file contents, starting w/ categories
+die "missing 'categories', stopped" unless exists $params->{categories};
+
+# write enum first
+print PARAM_HDR <<EOT;
+/* parameter categories */
+enum ${ns}_category_id_t {
+EOT
+my $num_categories = scalar @{$params->{categories}};
+foreach my $cat (@{$params->{categories}}) {
+    printf PARAM_HDR "    ${uc_ns}_CATEGORY_ID_%s,\n", $cat->{name};
+}
+# then write full contents tuple
+print PARAM_HDR <<EOT;
+    ${uc_ns}_NUM_CATEGORIES
+};
+
+struct ${ns}_category_t {
+    const enum ${ns}_category_id_t id;
+    const char *name;
+    const char *description;
+};
+
+/* array of category info for runtime usage */
+extern struct ${ns}_category_t ${ns}_categories[${uc_ns}_NUM_CATEGORIES];
+
+EOT
+
+print PARAM_C <<EOT;
+/* array of category info for runtime usage */
+struct ${ns}_category_t ${ns}_categories[${uc_ns}_NUM_CATEGORIES] = {
+EOT
+foreach my $cat (@{$params->{categories}}) {
+    my $desc = $cat->{description};
+    $desc =~ s/"/\\"/g;
+    printf PARAM_C qq(    { ) .
+        qq(${uc_ns}_CATEGORY_ID_%s,\n) .
+        qq(      "%s",\n) .
+        qq(      "%s" },\n),
+        $cat->{name}, $cat->{name}, $desc;
+}
+print PARAM_C <<EOT;
+};
+
+EOT
+
+
+########################################################################
+# now the actual parameters
+die "missing 'parameters', stopped" unless exists $params->{parameters};
+
+print PARAM_HDR <<EOT;
+/* parameter values */
+enum ${ns}_id_t {
+EOT
+my $num_params = @{$params->{parameters}};
+# XXX DJG TODO collate and separate by category
+foreach my $p (@{$params->{parameters}}) {
+    printf PARAM_HDR "    ${uc_ns}_ID_%s,\n", $p->{name};
+}
+print PARAM_HDR <<EOT;
+    ${uc_ns}_NUM_PARAMS
+};
+
+/* initializes parameter values from the environment */
+int ${ns}_init_params(void);
+
+enum ${ns}_type_t {
+    ${uc_ns}_TYPE_INVALID = 0,
+    ${uc_ns}_TYPE_INT,
+    ${uc_ns}_TYPE_DOUBLE,
+    ${uc_ns}_TYPE_BOOLEAN,
+    ${uc_ns}_TYPE_STRING
+};
+
+/* used to represent default values */
+struct ${ns}_param_default_val_t {
+    const enum ${ns}_type_t type;
+
+    /* not a union b/c of initialization portability issues */
+    const int i_val; /* also used for booleans */
+    const double d_val;
+    const char *s_val;
+};
+
+struct ${ns}_t {
+    const enum ${ns}_id_t id;
+    const char *name;
+    const char *description;
+    const struct ${ns}_param_default_val_t default_val;
+    /* TODO other fields here */
+};
+
+/* array of parameter info for runtime usage */
+extern struct ${ns}_t ${ns}_params[${uc_ns}_NUM_PARAMS];
+
+/* extern declarations for each parameter
+ * (definitions in $c_file) */
+EOT
+
+# XXX DJG TODO collate and separate by category
+foreach my $p (@{$params->{parameters}}) {
+    printf PARAM_HDR "extern %s ${uc_ns}_%s;\n",
+        type2ctype($p->{type}), $p->{name};
+}
+
+print PARAM_C <<EOT;
+/* array of parameter info for runtime usage */
+struct ${ns}_t ${ns}_params[${uc_ns}_NUM_PARAMS] = {
+EOT
+
+# XXX DJG TODO collate and separate by category
+foreach my $p (@{$params->{parameters}}) {
+    my $type_enum_val = "${uc_ns}_TYPE_".uc($p->{type});
+    my ($int_val, $str_val, $double_val) = (-1, qq(""), "0.0");
+
+    if ($p->{type} eq "string") {
+        $str_val = fmt_default($p->{default}, $p->{type});
+    }
+    elsif ($p->{type} eq "int") {
+        $int_val = fmt_default($p->{default}, $p->{type});
+    }
+    elsif ($p->{type} eq "double") {
+        $double_val = fmt_default($p->{default}, $p->{type});
+    }
+    elsif ($p->{type} eq "boolean") {
+        $int_val = fmt_default($p->{default}, $p->{type});
+    }
+    else {
+        die "unknown type $p->{type}, stopped";
+    }
+
+    my $desc = $p->{description};
+    $desc =~ s/"/\\"/g;
+
+    printf PARAM_C qq(    { ) .
+        qq(${uc_ns}_ID_%s,\n) .
+        qq(      "%s",\n) .
+        qq(      "%s",\n) .
+        #          T    I   D   S
+        qq(      { %s, %d, %s, %s } },\n),
+        $p->{name}, $p->{name}, $desc,
+        $type_enum_val, $int_val, $double_val, $str_val;
+}
+
+print PARAM_C <<EOT;
+};
+
+/* actual storage for parameters */
+EOT
+foreach my $p (@{$params->{parameters}}) {
+    printf PARAM_C "%s ${uc_ns}_%s = %s;\n",
+        type2ctype($p->{type}),
+        $p->{name},
+        fmt_default($p->{default}, $p->{type});
+}
+
+# FIXME the mpi_errno bit is MPICH-specific
+print PARAM_C <<EOT;
+
+#undef FUNCNAME
+#define FUNCNAME ${ns}_init_params
+#undef FCNAME
+#define FCNAME MPIU_QUOTE(FUNCNAME)
+int ${ns}_init_params(void)
+{
+    int mpi_errno = MPI_SUCCESS;
+    int rc;
+
+EOT
+
+foreach my $p (@{$params->{parameters}}) {
+    my $env_fn = type_to_env_fn($p->{type});
+    my @env_names = ();
+
+    # process extra envs first so the primary always wins
+    push @env_names, @{$p->{'abs-alt-env'}} if $p->{'abs-alt-env'};
+    push @env_names, map { "${uc_ns}_$_" } @{$p->{'alt-env'}};
+    push @env_names, "${uc_ns}_" . $p->{name};
+
+    foreach my $env_name (@env_names) {
+        # assumes rc is defined
+        my $var_name = "${uc_ns}_" . $p->{name};
+        print PARAM_C <<EOT;
+    rc = MPL_env2${env_fn}("$env_name", &($var_name));
+    MPIU_ERR_CHKANDJUMP1((-1 == rc),mpi_errno,MPI_ERR_OTHER,"**envvarparse","**envvarparse %s","$env_name");
+EOT
+    }
+    print PARAM_C "\n";
+}
+
+print PARAM_C <<EOT;
+fn_fail:
+    return mpi_errno;
+}
+
+EOT
+
+########################################################################
+# clean up
+
+close(PARAM_C);
+
+print PARAM_HDR "\n#endif /* $hdr_guard */\n";
+close(PARAM_HDR);
+
+
+########################################################################
+# helper subroutines
+
+# transform a parameter type to a C-language type
+sub type2ctype {
+    my $type = shift;
+    my %typemap = (
+        'int'     => 'int',
+        'double'  => 'double',
+        'string'  => 'const char *',
+        'boolean' => 'int',
+    );
+    die "unknown type '$type', stopped" unless exists $typemap{$type};
+    return $typemap{$type};
+}
+
+# transform a default value into a C value
+sub fmt_default {
+    my $val = shift;
+    my $type = shift;
+
+    if ($type eq "string") {
+        $val =~ s/"/\\"/g;
+        return qq("$val");
+    }
+    elsif ($type eq "boolean") {
+        if    ($val =~ m/^(0|f(alse)?|no?)$/i)   { return qq(0); }
+        elsif ($val =~ m/^(1|t(rue)?|y(es)?)$/i) { return qq(1); }
+        else {
+            warn "WARNING: type='$type', bad val='$val', continuing";
+            return qq(0); # fail-false
+        }
+    }
+    else {
+        return qq($val);
+    }
+}
+
+# turns foo_BAR-baz.h into FOO_BAR_BAZ_H_INCLUDED
+sub header_to_incl_guard {
+    my $header_file = shift;
+    my $guard = basename($header_file);
+    $guard =~ tr/a-z\-./A-Z__/;
+    $guard .= "_INCLUDED";
+    die "guard contains whitespace, stopped" if ($guard =~ m/\s/);
+    return $guard;
+}
+
+sub md5sum {
+    my $file = shift;
+    my $md5 = Digest::MD5->new();
+
+    open FILE, '<', $file;
+    binmode(FILE);
+    $md5->addfile(*FILE);
+    close FILE;
+
+    return $md5->hexdigest;
+}
+
+sub type_to_env_fn {
+    my $type = shift;
+    my %typemap = (
+        'int' =>  'int',
+        'string' => 'str',
+        'boolean' => 'bool',
+    );
+
+    die "unknown type '$type', stopped" unless exists $typemap{$type};
+    return $typemap{$type};
+}
+


Property changes on: mpich2/trunk/maint/genparams
___________________________________________________________________
Added: svn:executable
   + *

Added: mpich2/trunk/src/util/param/params.yml
===================================================================
--- mpich2/trunk/src/util/param/params.yml	                        (rev 0)
+++ mpich2/trunk/src/util/param/params.yml	2010-05-21 03:34:24 UTC (rev 6692)
@@ -0,0 +1,60 @@
+--- #YAML:1.0
+# This is a YAML formatted file with '#'-style comments.  This file
+# *must* be parseable by the YAML::Tiny perl module.  So don't use
+# the inline list or map forms and don't try to use any really fancy
+# features like tagging or anchors.
+#
+# The only tricky bit is that long reflowed text (such as a description)
+# should use ">-" to both fold newlines and remove the trailing newline.
+#
+# It is used to generate parameter-handling code for MPICH2.
+# See the maint/genparams script for more information.
+categories:
+    - name        : collective
+      description : parameters that control collective communication behavior
+
+parameters:
+    ##############################################################
+    # collective parameters
+    - category    : collective
+      name        : ALLTOALL_SHORT_MSG_SIZE
+      type        : int
+      default     : 256
+      description : >-
+        the short message algorithm will be used if the per-destination
+        message size (sendcount*size(sendtype)) is <= this value
+
+    - category    : collective
+      name        : ALLTOALL_MEDIUM_MSG_SIZE
+      type        : int
+      default     : 32768
+      description : >-
+        the medium message algorithm will be used if the per-destination
+        message size (sendcount*size(sendtype)) is <= this value and
+        larger than ALLTOALL_SHORT_MSG_SIZE
+
+    - category    : collective
+      name        : ALLTOALL_THROTTLE
+      type        : int
+      default     : 4
+      description : >-
+        max no. of irecvs/isends posted at a time in some alltoall
+        algorithms. Setting it to 0 causes all irecvs/isends to be
+        posted at once.
+
+    ##############################################################
+    # intranode communication parameters
+    - category    : intranode
+      name        : NOLOCAL
+      alt-env     :
+                    - NO_LOCAL
+      abs-alt-env :
+                    - MPICH_NOLOCAL
+                    - MPICH_NO_LOCAL
+      type        : boolean
+      default     : false
+      description : >-
+        If true, force all processes to operate as though all processes
+        are located on another node.  For example, this disables shared
+        memory communication hierarchical collectives.
+...



More information about the mpich2-commits mailing list