[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 ----
Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Re: distributed octave,
JD Cole <=
- Re: distributed octave, Jason Tillett, 2003/11/20