help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: distributed octave


From: JD Cole
Subject: Re: distributed octave
Date: Wed, 19 Nov 2003 23:08:28 -0800
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031007

Hey Jason,
I think I worked out the problem, I tried you test script and my api_example.m with no problems. Not sure how this stuff was working before in the state it was in, but I guess that's more of a personal problem :-).

I have attached a new src/octave.cc and the corresponding patch, it's you're choice. I'll try to get a new distribution out on the website once it's been put through the motions.

Sorry for the trouble,
   JD
jason tillett wrote:

Hi JD,

I really appreciate your correspondence.
You did clarify some questions I had. I can summarize my progress
for you.

I can now distribute the process for example...(I am working
only with the api)

mpirun -np 2 octave /mfiles/test.m --parallel /pathToPil/pil_file

After running the command line above, I can verify that each
node in the cluster is executing it. (here just 2 nodes because
non-0 nodes are writing to a file)

test.m is here
----------------------------------------------------------
mpi_init();

rank = mpi_comm_rank ('comm_world');
wsize = mpi_comm_size ('comm_world');
machname="default machine name";
machtype="default machine type";

msg_tag = 1;

if rank ==0
       machname="master name";
       machtype="master type";

     printf ("%s: %s\n", machname, machtype);
       myfile=fopen("master.txt","w","ieee-le");
       fprintf(myfile,"hello\n");
       fclose(myfile);
else
     printf ("%s: %s\n", machname, machtype);
       myfile=fopen("slave.txt","w","ieee-le");
       fprintf(myfile,"hello\n");
       fclose(myfile);
end

mpi_finalize();
-------------------------------------------------------------------------

The directory /mfiles is  exported by node 0 and mounted by the other
nodes. I have verified that all other nodes can read and write to mfiles
as the user that is running the octave process.

What happens when I run the command line is that it finishes with no errors
but no output is written by any processes other than node 0 (the node the
command line is run on). Node 0 creates the file master.txt but slave.txt is
not created.

Here is the output of the run...
-------------------------------------------------------------------------
address@hidden mfiles]$ mpirun -np 2 octave /mfiles/test.m --parallel
/usr/local/src/mpi_pil-sp20040402/octave_mpi.pil
GNU Octave, version 2.1.45 (i686-pc-linux-gnu).
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 John W. Eaton.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTIBILITY or
FITNESS FOR A PARTICULAR PURPOSE.  For details, type `warranty'.

Please contribute if you find this software useful.
For more information, visit http://www.octave.org/help-wanted.html

Report bugs to <address@hidden>.

master name: master type
address@hidden mfiles]$
--------------------------------------------------------------------------

So at this point I'm trying to figure out just what the non-0 node(s)
is(are) doing.

I created test.m because code with blocking send and receives would hang.
I'm glad you contacted me because I was going to scratch my head for a while
before contacting you.

Sincerely Yours,
Jason










----- Original Message ----- From: "JD Cole" <address@hidden>
To: "Jason Tillett" <address@hidden>
Sent: Tuesday, November 18, 2003 10:09 PM
Subject: Re: distributed octave


Hey Jason,
   Any luck with that explanation I gave you. I'd hate for you to go
"code-diving" without a wetsuit.

Best,

JD



/*

Copyright (C) 1996, 1997 John W. Eaton

This file is part of Octave.

Octave 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 2, or (at your option) any
later version.

Octave 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 Octave; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

// Born February 20, 1992.

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <cassert>
#include <cstdlib>
#include <cstring>
#include <ctime>

#include <fstream>
#include <iostream>

#ifdef HAVE_UNISTD_H
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <unistd.h>
#endif

#include "cmd-edit.h"
#include "f77-fcn.h"
#include "file-ops.h"
#include "file-stat.h"
#include "lo-error.h"
#include "oct-env.h"
#include "pathsearch.h"
#include "str-vec.h"

#include <defaults.h>
#include "Cell.h"
#include "defun.h"
#include "error.h"
#include "file-io.h"
#include "input.h"
#include "lex.h"
#include "octave.h"
#include "oct-hist.h"
#include "oct-obj.h"
#include "oct-pi.h"
#include "ops.h"
#include "toplev.h"
#include "parse.h"
#include "pt-plot.h"
#include "procstream.h"
#include "prog-args.h"
#include "sighandlers.h"
#include "sysdep.h"
#include "ov.h"
#include "unwind-prot.h"
#include "utils.h"
#include "variables.h"
#include <version.h>

// Kluge.
extern "C" void F77_FUNC (xerbla, XERBLA) (const char *, int, long);

extern void install_builtins (void);

#if !defined (HAVE_ATEXIT) && defined (HAVE_ON_EXIT)
extern "C" int on_exit ();
#define atexit on_exit
#endif

// The command-line options.
static string_vector octave_argv;

// TRUE means we read ~/.octaverc and ./.octaverc.
// (--norc; --no-init-file; -f)
static bool read_init_files = true;

// TRUE means we read the site-wide octaverc files.
// (--norc; --no-site-file; -f)
static bool read_site_files = true;

// TRUE means we don't print the usual startup message.
// (--quiet; --silent; -q)
static bool inhibit_startup_message = false;

// TRUE means we turn on compatibility options.
// (--traditional)
static bool traditional = false;

// If TRUE, print verbose info in some cases.
// (--verbose; -V)
static bool verbose_flag = false;

// Usage message
static const char *usage_string = 
  "octave [-?HVdfhiqvx] [--debug] [--echo-commands] [--exec-path path]\n\
       [--funcall FUNC] [--help] [--info-file file] [--info-program prog]\n\
       [--interactive] [--no-history] [--no-init-file] [--no-line-editing]\n\
       [--no-site-file] [-p path] [--parallel file] [--path path]\n\
       [--silent] [--traditional] [--verbose] [--version] [file]";

// This is here so that it's more likely that the usage message and
// the real set of options will agree.  Note: the `+' must come first
// to prevent getopt from permuting arguments!
static const char *short_opts = "+?HVdfhip:qvx";

// The name of the optional initial function to call at startup.
// (--funcall FUNC)
static std::string fun_to_call;

// Long options.  See the comments in getopt.h for the meanings of the
// fields in this structure.
#define EXEC_PATH_OPTION 1
#define FUNCALL_OPTION 2
#define INFO_FILE_OPTION 3
#define INFO_PROG_OPTION 4
#define NO_INIT_FILE_OPTION 5
#define NO_LINE_EDITING_OPTION 6
#define NO_SITE_FILE_OPTION 7
#define TRADITIONAL_OPTION 8
#define PARALLEL_OPTION 9

long_options long_opts[] =
  {
    { "debug",            prog_args::no_arg,       0, 'd' },
    { "braindead",        prog_args::no_arg,       0, TRADITIONAL_OPTION },
    { "echo-commands",    prog_args::no_arg,       0, 'x' },
    { "exec-path",        prog_args::required_arg, 0, EXEC_PATH_OPTION },
    { "funcall",          prog_args::required_arg,  0, FUNCALL_OPTION },
    { "help",             prog_args::no_arg,       0, 'h' },
    { "info-file",        prog_args::required_arg, 0, INFO_FILE_OPTION },
    { "info-program",     prog_args::required_arg, 0, INFO_PROG_OPTION },
    { "interactive",      prog_args::no_arg,       0, 'i' },
    { "no-history",       prog_args::no_arg,       0, 'H' },
    { "no-init-file",     prog_args::no_arg,       0, NO_INIT_FILE_OPTION },
    { "no-line-editing",  prog_args::no_arg,       0, NO_LINE_EDITING_OPTION },
    { "no-site-file",     prog_args::no_arg,       0, NO_SITE_FILE_OPTION },
    { "norc",             prog_args::no_arg,       0, 'f' },
    { "parallel",         prog_args::required_arg, 0, PARALLEL_OPTION },
    { "path",             prog_args::required_arg, 0, 'p' },
    { "quiet",            prog_args::no_arg,       0, 'q' },
    { "silent",           prog_args::no_arg,       0, 'q' },
    { "traditional",      prog_args::no_arg,       0, TRADITIONAL_OPTION },
    { "verbose",          prog_args::no_arg,       0, 'V' },
    { "version",          prog_args::no_arg,       0, 'v' },
    { 0,                  0,                       0, 0 }
  };

// Store the command-line options for later use.

static void
intern_argv (int argc, char **argv)
{
  bind_builtin_variable ("nargin", argc-1, true, true, 0);

  Cell octave_argv;

  if (argc > 1)
    {
      Array<octave_value> tmp (argc-1);

      // Skip program name in argv.
      int i = argc;
      while (--i > 0)
        tmp(i-1) = octave_value (*(argv+i));

      octave_argv = Cell (tmp, argc-1, 1);
    }

  bind_builtin_constant ("argv", octave_argv, true, true);
}

static void
initialize_pathsearch (void)
{
  // This may seem odd, but doing it this way means that we don't have
  // to modify the kpathsea library...

  std::string odb = octave_env::getenv ("OCTAVE_DB_PATH");

  // For backward compatibility.

  if (odb.empty ())
    odb = octave_env::getenv ("OCTAVE_DB_DIR");

  if (odb.empty ())
    odb = Vdata_dir + file_ops::dir_sep_str + "octave:"
      + Vlibexec_dir + file_ops::dir_sep_str + "octave";

  octave_original_texmfdbs = octave_env::getenv ("TEXMFDBS");

  octave_env::putenv ("TEXMFDBS", odb);
}

// Initialize by reading startup files.

static void
execute_startup_files (void)
{
  unwind_protect::begin_frame ("execute_startup_files");

  // XXX FIXME XXX -- need to make it possible to set this in startup
  // files.

  unwind_protect_bool (input_from_startup_file);

  input_from_startup_file = true;

  int verbose = (verbose_flag && ! inhibit_startup_message);

  if (read_site_files)
    {
      // Execute commands from the site-wide configuration file.
      // First from the file $(prefix)/lib/octave/site/m/octaverc
      // (if it exists), then from the file
      // $(prefix)/share/octave/$(version)/m/octaverc (if it exists).

      parse_and_execute (Vlocal_site_defaults_file, verbose);

      parse_and_execute (Vsite_defaults_file, verbose);
    }

  if (read_init_files)
    {
      // Try to execute commands from $HOME/$OCTAVE_INITFILE and
      // $OCTAVE_INITFILE.  If $OCTAVE_INITFILE is not set, .octaverc
      // is assumed.

      int home_rc_already_executed = 0;

      std::string initfile = octave_env::getenv ("OCTAVE_INITFILE");

      if (initfile.empty ())
        initfile = ".octaverc";

      std::string home_dir = octave_env::get_home_directory ();

      std::string home_rc = home_dir + file_ops::dir_sep_str + initfile;
      std::string local_rc
        = octave_env::getcwd () + file_ops::dir_sep_str + initfile;

      if (! home_dir.empty ())
        {
          parse_and_execute (home_rc, verbose);

          // Names alone are not enough.

          file_stat fs_home_rc (home_rc);

          if (fs_home_rc)
            {
              file_stat fs_dot_rc (local_rc);

              if (fs_dot_rc && fs_home_rc.ino () == fs_dot_rc.ino ())
                home_rc_already_executed = 1;
            }
        }

      if (! home_rc_already_executed)
        parse_and_execute (local_rc, verbose);
    }

  unwind_protect::run_frame ("execute_startup_files");
}

// Usage message with extra help.

static void
verbose_usage (void)
{
  std::cout << OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY "\n\
\n\
Usage: octave [options]\n\
\n\
Options:\n\
\n\
  --debug, -d             Enter parser debugging mode.\n\
  --echo-commands, -x     Echo commands as they are executed.\n\
  --exec-path PATH        Set path for executing subprograms.\n\
  --funcall FUNC          Call Octave function FUNC with no arguments.\n\
  --help, -h, -?          Print short help message and exit.\n\
  --info-file FILE        Use top-level info file FILE.\n\
  --info-program PROGRAM  Use PROGRAM for reading info files.\n\
  --interactive, -i       Force interactive behavior.\n\
  --no-history, -H        Don't save commands to the history list\n\
  --no-init-file          Don't read the ~/.octaverc or .octaverc files.\n\
  --no-line-editing       Don't use readline for command-line editing.\n\
  --no-site-file          Don't read the site-wide octaverc file.\n\
  --norc, -f              Don't read any initialization files.\n\
  --path PATH, -p PATH    Set initial LOADPATH to PATH.\n\
  --parallel FILE         Enable parallel support.\n\
  --silent, -q            Don't print message at startup.\n\
  --traditional           Set compatibility variables.\n\
  --verbose, -V           Enable verbose output in some cases.\n\
  --version, -v           Print version number and exit.\n\
\n\
  FILE                    Execute commands from FILE.\n\
\n\
Additional information about Octave is available via the WWW at\n\
http://www.octave.org.\n\
\n"
OCTAVE_CONTRIB_STATEMENT "\n\
\n"
OCTAVE_BUGS_STATEMENT "\n";

  exit (0);
}

// Terse usage messsage.

static void
usage (void)
{
  std::cerr << "usage: " << usage_string << "\n";
  exit (1);
}

static void
print_version_and_exit (void)
{
  std::cout << OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_WARRANTY_AND_BUGS "\n";
  exit (0);
}

static void
initialize_error_handlers ()
{
  set_liboctave_error_handler (error);
  set_liboctave_warning_handler (warning);
}

// What happens on --traditional.

static void
maximum_braindamage (void)
{
  bind_builtin_variable ("PS1", ">> ");
  bind_builtin_variable ("PS2", "");
  bind_builtin_variable ("beep_on_error", true);
  bind_builtin_variable ("crash_dumps_octave_core", false);
  bind_builtin_variable ("default_eval_print_flag", false);
  bind_builtin_variable ("default_global_variable_value", Matrix ());
  bind_builtin_variable ("default_save_format", "mat-binary");
  bind_builtin_variable ("define_all_return_values", true);
  bind_builtin_variable ("do_fortran_indexing", true);
  bind_builtin_variable ("fixed_point_format", true);
  bind_builtin_variable ("implicit_num_to_str_ok", true);
  bind_builtin_variable ("implicit_str_to_num_ok", true);
  bind_builtin_variable ("initialize_global_variables", true);
  bind_builtin_variable ("ok_to_lose_imaginary_part", true);
  bind_builtin_variable ("page_screen_output", false);
  bind_builtin_variable ("prefer_column_vectors", false);
  bind_builtin_variable ("print_empty_dimensions", false);
  bind_builtin_variable ("treat_neg_dim_as_zero", true);
  bind_builtin_variable ("warn_function_name_clash", false);
  bind_builtin_variable ("whitespace_in_literal_matrix", "traditional");
}

// You guessed it.

int
octave_main (int argc, char **argv)
{
  octave_env::set_program_name (argv[0]);

  dir_path::set_program_name (argv[0]);

  // The order of these calls is important.  The call to
  // install_defaults must come before install_builtins because
  // default variable values must be available for the variables to be
  // installed, and the call to install_builtins must come before the
  // options are processed because some command line options override
  // defaults by calling bind_builtin_variable.

  sysdep_init ();

  // The idea here is to force xerbla to be referenced so that we will
  // link to our own version instead of the one provided by the BLAS
  // library.  But octave_NaN should never be -1, so we should never
  // actually call xerbla.

  if (octave_NaN == -1)
    F77_FUNC (xerbla, XERBLA) ("octave", 13, 6L);

  initialize_error_handlers ();

  install_defaults ();

  initialize_pathsearch ();

  install_signal_handlers ();

  initialize_file_io ();

  initialize_symbol_tables ();

  install_types ();

  install_ops ();

  install_builtins ();

  // Before parsing anything, command line arguments need to be passed
  // to parallel initialization libraries. (They may strip some arguments.)
  pi_error opi_err;

  opi_err = octave_parallel_interface::initialize (&argc, &argv);

  // !! perhaps this should be called from intialize
  octave_parallel_interface::install_builtins ();

  prog_args args (argc, argv, short_opts, long_opts);

  int optc;
  while ((optc = args.getopt ()) != EOF)
    {
      switch (optc)
        {
        case 'H':
          bind_builtin_variable ("saving_history", false);
          break;

        case 'V':
          verbose_flag = true;
          break;

        case 'd':
          yydebug++;
          break;

        case 'f':
          read_init_files = false;
          read_site_files = false;
          break;

        case 'h':
        case '?':
          verbose_usage ();
          break;

        case 'i':
          forced_interactive = true;
          break;

        case 'p':
          if (args.optarg ())
            bind_builtin_variable ("LOADPATH", args.optarg ());
          break;

        case 'q':
          inhibit_startup_message = true;
          break;

        case 'x':
          {
            double tmp = (ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_CMD_LINE);
            bind_builtin_variable ("echo_executing_commands", tmp);
          }
          break;

        case 'v':
          print_version_and_exit ();
          break;

        case EXEC_PATH_OPTION:
          if (args.optarg ())
            bind_builtin_variable ("EXEC_PATH", args.optarg ());
          break;

        case FUNCALL_OPTION:
          if (args.optarg ())
            fun_to_call = args.optarg ();
          break;

        case INFO_FILE_OPTION:
          if (args.optarg ())
            bind_builtin_variable ("INFO_FILE", args.optarg ());
          break;

        case INFO_PROG_OPTION:
          if (args.optarg ())
            bind_builtin_variable ("INFO_PROGRAM", args.optarg ());
          break;

        case NO_INIT_FILE_OPTION:
          read_init_files = false;
          break;

        case NO_LINE_EDITING_OPTION:
          line_editing = false;
          break;

        case NO_SITE_FILE_OPTION:
          read_site_files = 0;
          break;

        case PARALLEL_OPTION:
          // !! This should do nothing
          if (args.optarg ())
            std::string arg = args.optarg ();

          if (opi_err != no_error)
            {
              std::string msg ="PIL:" + 
                octave_parallel_interface::get_error_string ();
              
              error(msg.c_str ());

              usage ();
            }
          break;

        case TRADITIONAL_OPTION:
          traditional = true;
          break;

        default:
          usage ();
          break;
        }
    }

#if defined (HAVE_ATEXIT) || defined (HAVE_ON_EXIT)
  // Make sure we clean up when we exit.  Also allow users to register
  // functions.  If we don't have atexit or on_exit, we're going to
  // leave some junk files around if we exit abnormally.

  atexit (do_octave_atexit);
#endif

  // These can come after command line args since none of them set any
  // defaults that might be changed by command line options.

  initialize_command_input ();

  if (! inhibit_startup_message)
    std::cout << OCTAVE_STARTUP_MESSAGE "\n" << std::endl;

  if (traditional)
    maximum_braindamage ();

  octave_interpreter_ready = true;

  execute_default_pkg_add_files ();

  execute_startup_files ();

  command_history::read (false);

  if (! inhibit_startup_message && reading_startup_message_printed)
    std::cout << std::endl;

  // Avoid counting commands executed from startup files.

  command_editor::reset_current_command_number (1);

  // if its not a pen, its business as usual

  // If there is an extra argument, see if it names a file to read.
  // Additional arguments are taken as command line options for the
  // script.

  int last_arg_idx = args.optind ();

  int remaining_args = argc - last_arg_idx;

  if (remaining_args > 0)
    {
      reading_script_file = true;

      curr_fcn_file_name = argv[last_arg_idx];
      curr_fcn_file_full_name = curr_fcn_file_name;

      FILE *infile = get_input_from_file (curr_fcn_file_name);

      if (infile)
        {
          input_from_command_line_file = true;

          bind_builtin_variable ("program_invocation_name",
                                 curr_fcn_file_name);

          size_t pos
            = curr_fcn_file_name.find_last_of (file_ops::dir_sep_chars);

          std::string tmp = (pos != NPOS)
            ? curr_fcn_file_name.substr (pos+1) : curr_fcn_file_name;

          bind_builtin_variable ("program_name", tmp);

          intern_argv (remaining_args, argv+last_arg_idx);

          command_editor::blink_matching_paren (false);

          switch_to_buffer (create_buffer (infile));
        }
      else
        clean_up_and_exit (1);
    }
  // If this is a pen node, start its server
  // !! Location picked from Andy Jacobson's octave-mpi
  else if (octave_parallel_interface::get_type () == 
evaluation_node_info::pen_type)
    {
      octave_parallel_interface::pen_server ();

      clean_up_and_exit (0);

      return 0;
    }

  else
    {
      // Is input coming from a terminal?  If so, we are probably
      // interactive.

      interactive = (isatty (fileno (stdin)) && isatty (fileno (stdout)));

      intern_argv (argc, argv);

      switch_to_buffer (create_buffer (get_input_from_stdin ()));
    }

  // Force input to be echoed if not really interactive, but the user
  // has forced interactive behavior.

  if (! interactive && forced_interactive)
    {
      command_editor::blink_matching_paren (false);

      // XXX FIXME XXX -- is this the right thing to do?

      bind_builtin_variable ("echo_executing_commands", ECHO_CMD_LINE);
    }

  if (! interactive)
    line_editing = false;

  int retval = main_loop (fun_to_call);

  if (retval == 1 && ! error_state)
    retval = 0;

  // If this was a command line run, the remote nodes still
  // have to wait for the quit command from the main node
  if (input_from_command_line_file
      && octave_parallel_interface::get_type () == 
evaluation_node_info::pen_type)
    {
      octave_parallel_interface::pen_server ();
    }
      
  clean_up_and_exit (retval);

  return 0;
}

/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/
*** src/octave.cc       2003-11-19 22:54:04.000000000 -0800
--- /home/jd/hpo/code/c/octave-cvs/src/octave.cc        2003-04-23 
16:24:15.000000000 -0700
***************
*** 571,576 ****
--- 571,587 ----
  
    command_editor::reset_current_command_number (1);
  
+   // If this is a pen node, start its server
+   // !! Location picked from Andy Jacobson's octave-mpi
+   if (octave_parallel_interface::get_type () == 
evaluation_node_info::pen_type)
+     {
+       octave_parallel_interface::pen_server ();
+ 
+       clean_up_and_exit (0);
+ 
+       return 0;
+     }
+ 
    // if its not a pen, its business as usual
  
    // If there is an extra argument, see if it names a file to read.
***************
*** 614,630 ****
        else
        clean_up_and_exit (1);
      }
-   // If this is a pen node, start its server
-   // !! Location picked from Andy Jacobson's octave-mpi
-   else if (octave_parallel_interface::get_type () == 
evaluation_node_info::pen_type)
-     {
-       octave_parallel_interface::pen_server ();
- 
-       clean_up_and_exit (0);
- 
-       return 0;
-     }
- 
    else
      {
        // Is input coming from a terminal?  If so, we are probably
--- 625,630 ----
***************
*** 657,670 ****
    if (retval == 1 && ! error_state)
      retval = 0;
  
-   // If this was a command line run, the remote nodes still
-   // have to wait for the quit command from the main node
-   if (input_from_command_line_file
-       && octave_parallel_interface::get_type () == 
evaluation_node_info::pen_type)
-     {
-       octave_parallel_interface::pen_server ();
-     }
-       
    clean_up_and_exit (retval);
  
    return 0;
--- 657,662 ----

reply via email to

[Prev in Thread] Current Thread [Next in Thread]