parallel run of executable within MPI in C++ - c++

i have been using MPI for a while, but i'm not experienced. So
i'm here to ask an advice on general structure of the following implementation.
Say, I have the main C++ file with
MPI_Init(&narg,&arg);
int me,nprocs;
MPI_Comm_rank(MPI_COMM_WORLD,&me);
MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
int N = 10;
for (int i=0;i<N;i++) {
//(1)do some stuff in parallel...
//(2)gather results and write an input file for executable
MPI_Barrier(MPI_COMM_WORLD);
//(3)run executable in parallel.
// which is usually run from command line as:
//
// mpirun -np 6 external.exe < input.file
//
MPI_Barrier(MPI_COMM_WORLD);
//(4)gather output from executable, distribute info among processors and keep running
}
MPI_Finalize();
it's the (3) where i have a problem understanding how to do it and tell how many processors can it use. My confusion is also that some kind of "run" command should probably be executed from a single processor/instance. So how do i make it work and let parallel executable use all processors which were provided to the main program? If it is possible.
p/s/ i saw similar questions here in stackoverflow, but no definite answer on if it is possible or not.

Do you have control over the exe, i.e. can you change its code? If so, I'd suggest re-developing it so that the exe is simply a wrapper around the behavior you need, and then you can link in the actual action into your application.
If that is not an option, I suggest just calling the executable from your master (rank 0) process, and let the others wait. Not super efficient, but it'll do the job:
if (me == 0) {
system("mpirun -np 6 external.exe < input.file")
}
You'll have to figure out a way to wait until the command is finished, but according to the docs of system and mpirun it should be as simple as checking if the return value from system(...) is zero, and then continue (after a barrier, as in your example).

Related

pidof from a background script for another background process

I wrote a c++ program to check if a process is running or not . this process is independently launched at background . my program works fine when I run it on foreground but when I time schedule it, it do not work .
int PID= ReadCommanOutput("pidof /root/test/testProg1"); /// also tested with pidof -m
I made a script in /etc/cron.d/myscript to time schedule it as follows :-
45 15 * * * root /root/ProgramMonitor/./testBkg > /root/ProgramMonitor/OutPut.txt
what could be the reason for this ?
string ReadCommanOutput(string command)
{
string output="";
int its=system((command+" > /root/ProgramMonitor/macinfo.txt").c_str());
if(its==0)
{
ifstream reader1("/root/ProgramMonitor/macinfo.txt",fstream::in);
if(!reader1.fail())
{
while(!reader1.eof())
{
string line;
getline(reader1,line);
if(reader1.fail())// for last read
break;
if(!line.empty())
{
stringstream ss(line.c_str());
ss>>output;
cout<<command<<" output = ["<<output<<"]"<<endl;
break;
}
}
reader1.close();
remove("/root/ProgramMonitor/macinfo.txt");
}
else
cout<<"/root/ProgramMonitor/macinfo.txt not found !"<<endl;
}
else
cout<<"ERROR: code = "<<its<<endl;
return output;
}
its output coming as "ERROR: code = 256"
thanks in advacee .
If you really wanted to pipe(2), fork(2), execve(2) then read the output of a pidof command, you should at least use popen(3) since ReadCommandOutput is not in the Posix API; at the very least
pid_t thepid = 0;
FILE* fpidof = popen("pidof /root/test/testProg1");
if (fpidof) {
int p=0;
if (fscanf(fpidof, "%d", &p)>0 && p>0)
thepid = (pid_t)p;
pclose(fpidof);
}
BTW, you did not specify what should happen if several processes (or none) are running the testProg1....; you also need to check the result of pclose
But you don't need to; actually you'll want to build, perhaps using snprintf, the pidof command (and you should be scared of code injection into that command, so quote arguments appropriately). You could simply find your command by accessing the proc(5) file system: you would opendir(3) on "/proc/", then loop on readdir(3) and for every entry which has a numerical name like 1234 (starts with a digit) readlink(2) its exe entry like e.g. /proc/1234/exe ...). Don't forget the closedir and test every syscall.
Please read Advanced Linux Programming
Notice that libraries like Poco or toolkits like Qt (which has a layer QCore without any GUI, and providing QProcess ....) could be useful to you.
As to why your pidof is failing, we can't guess (perhaps a permission issue, or perhaps there is no more any process like you want). Try to run it as root in another terminal at least. Test its exit code, and display both its stdout & stderr at least for debugging purposes.
Also, a better way (assuming that testProg1 is some kind of a server application, to be run in at most one single process) might be to define different conventions. Your testProg1 might start by writing its own pid into /var/run/testProg1.pid and your current application might then read the pid from that file and check, with kill(2) and a 0 signal number, that the process is still existing.
BTW, you could also improve your crontab(5) entry. You could make it run some shell script which uses logger(1) and (for debugging) runs pidof with its output redirected elsewhere. You might also read the mail perhaps sent to root by cron.
Finally I solved this problem by using su command
I have used
ReadCommanOutput("su -c 'pidof /root/test/testProg1' - root");
insteadof
ReadCommanOutput("pidof /root/test/testProg1");

Does a program started with mpiexec know it was started with mpiexec?

I'm in the process of adding an option to a Fortran program to run it using multiple processors using MPI. If the user is going to run it in parallel, the user needs to specify different input files---one file for each domain (processor) of the problem. The program will look for a specific filename by default (a file called "serial.inp"). So I need the program to know when it is being run in parallel so that it can instead look for the other filenames instead (e.g. "parallel_1.inp", "parallel_2.inp", "parallel_3.inp", etc.). My first thought is to have the user pass an argument to the program when they execute it, e.g.:
mpiexec -n 4 myprogram.exe -parallel
This way, it will look for the parallel files when that argument is present. But it seems kind of redundant. If the program is being called with mpiexec, there is no question that the user is attempting to run it in parallel. Is there any way that my program will know it was started using mpiexec? Or is the command line argument my best bet?
Alex Leach is right in that you can do this with MPI-implementation-specific environment variable lookups, but there's no portable way to do this.
But as I understand, I don't think you really need to; you can get most of what you want with just checking to see if it was run with one rank:
program filenames
use mpi
implicit none
integer :: comsize, rank, ierr
character(len=128) :: inputfilename
call MPI_Init(ierr)
call MPI_Comm_size(MPI_COMM_WORLD,comsize,ierr)
call MPI_Comm_rank(MPI_COMM_WORLD,rank,ierr)
if (comsize == 1) then
inputfilename = 'serial.inp'
else
write(inputfilename, '(A,I0,A)'), 'parallel_',rank,'.imp'
endif
write(*,'(I,1X,A)'), rank, trim(inputfilename)
call MPI_Finalize(ierr)
end program filenames
Running gives
$ mpirun -np 4 ./filenames
0 parallel_0.imp
1 parallel_1.imp
2 parallel_2.imp
3 parallel_3.imp
$ ./filenames
0 serial.inp
That's not perfect; it'll give the serial result if you run using mpirun -np 1 filenames, but depending on your use case that may not be a terrible thing in exchange for having something portable.
Processes run with mpiexec will have various environment variables set, indicating to the subprocesses whether they are the master process or slaves, amongst other things.
Look in your mpiexec's documentation for specific details. Microsoft have some documentation online too.
Why not do it programmatically? This is how I do it in my program:
#ifdef MPI
CALL MPI_Init(ierr) ! Initialize MPI
CALL MPI_Comm_rank(mpicomm,nproc,ierr) ! Who am I?
CALL MPI_Comm_size(mpicomm,size,ierr) ! How many processes?
#else
nproc = 0
size = 1
#endif
After this point in the program, you can inquire whether the program is serial or parallel by inquiring the value of size.

What are the possible causes of "BUG: scheduling while atomic?"

There is another process continuously creating files that need processing by this code.
This code constantly scans the file-system for new files that need processing by comparing the contents of the file-system against a sqlite database that contains the processing results - one record for each file. This process is running at nice -n 19 so as not to interfere with the creation of new files by the other process.
It all works perfectly for a large number (>1k) of files, but then blows up with BUG: scheduling while atomic.
According to this
"Scheduling while atomic" indicates that you've tried to sleep
somewhere that you shouldn't
But the only sleep in the code is like this
void doFiles(void) {
for (...) { // for each file in the file-system
... // check database - do processing if needed
}
sleep(1);
}
int main(int argc, char *argv[], char *envp[]) {
while (true) doFiles();
return -1;
}
The code will hit this sleep after it has checked every file in the file-system against the database. The process needs to be repeated since new files will be added from time to time. There is no multi-threading in this code. Are there other possible causes for "BUG: scheduling while atomic" besides a misplaced sleep?
Edit: additional error output:
note: mirlin[1083] exited with preempt_count 1
BUG: scheduling while atomic: mirlin/1083/0x40000002
Modules linked in: g_cdc_ms musb_hdrc nop_usb_xceiv irqk edmak dm365mmap cmemk
Backtrace:
[<c002a5a0>] (dump_backtrace+0x0/0x110) from [<c028e56c>] (dump_stack+0x18/0x1c)
r6:c1099460 r5:c04ea000 r4:00000000 r3:20000013
[<c028e554>] (dump_stack+0x0/0x1c) from [<c00337b8>] (__schedule_bug+0x58/0x64)
[<c0033760>] (__schedule_bug+0x0/0x64) from [<c028e864>] (schedule+0x84/0x378)
r4:c10992c0 r3:00000000
[<c028e7e0>] (schedule+0x0/0x378) from [<c0033a80>] (__cond_resched+0x28/0x38)
[<c0033a58>] (__cond_resched+0x0/0x38) from [<c028ec6c>] (_cond_resched+0x34/0x44)
r4:00013000 r3:00000001
[<c028ec38>] (_cond_resched+0x0/0x44) from [<c0082f64>] (unmap_vmas+0x570/0x620)
[<c00829f4>] (unmap_vmas+0x0/0x620) from [<c0085c10>] (exit_mmap+0xc0/0x1ec)
[<c0085b50>] (exit_mmap+0x0/0x1ec) from [<c0037610>] (mmput+0x40/0xfc)
r9:00000001 r8:80000005 r6:c04ea000 r5:00000000 r4:c0427300
[<c00375d0>] (mmput+0x0/0xfc) from [<c003b5e4>] (exit_mm+0x150/0x158)
r5:c10992c0 r4:c0427300
[<c003b494>] (exit_mm+0x0/0x158) from [<c003cd44>] (do_exit+0x198/0x67c)
r7:c03120d1 r6:c10992c0 r5:0000000b r4:c10992c0
...
As others have said, you can sleep() anytime you want to in user code.
Looks like a problem with a driver on your platform. The driver may not actually call sleep() or schedule(), but often it will make a call of an kernel function which will, in turn, call one of these.
This also looks like it is using memory mapped file I/O on an embedded TI ARM processor.
This error was caused by a bad build.
A clean build by itself did not help.
A fresh checkout and build was required to resolve this issue.

How to detect file leak and the corresponding code in Solaris?

How to detect file leak and the corresponding stack in Solaris? I see the information was well reported by valgrind on Linux. Please let me know if we have any tools on Solaris also?
On Linux you can use strace to log all file open and close calls. Then you can analyse the log on Resource Leak - the number of open calls should match the number of close calls. If this is not true then you have a leak. On Solaris there is a similar tool - DTrace.
You can, in Solaris, look at currently open filedescriptors of a process by simply using the pfiles command. If you want to track files being opened/closed, truss (the Solaris equivalent to strace) comes to mind, with a filter for file-related syscalls (truss -e open,close but there are others that create filedescriptors).
If you find that the pfiles output grows, first identify whether what you're leaking are ordinary files or things like sockets / pipes. If it's leaking ordinary files, then a dtrace script can be used; the following is a base for own experiments, I currently don't have a Solaris system at hand to try it out and refine it. See below.
#!/usr/bin/dtrace -s
syscall::open:entry { self->t = ustack(); }
syscall::open:return /arg0 >= 0/ { trackedfds[arg0] = self->t; }
syscall::open:return { self->t = 0; }
syscall::close:entry { self->t = arg0; }
syscall::close:return /arg0 >= 0/ { trackedfds[self->t] = 0; }
syscall::close:return { self->t = 0; }
END { printa(trackedfds); }
This builds an associative array indexed by filedescriptor number whose contents are the userside stacktrace at the time of the open() system call. On successful close, the entry for the given filedescriptor number is discarded, and when the program exits (or the script is stopped) the remaining contents of said associative array are printed - if anything's left, that'd be a candidate for leaks.
Note that the END {} probe might not be the correct place for this; proc::exit or something of the like may be required. It depends on when exactly this triggers, before or after the cleanup done at program teardown (exiting / killing a program closes all its filedescriptors, which would erase the trackedfds[] array). That's why I've said above this is a starting point, I can't check without a Solaris system.

Problems with system() calls in Linux

I'm working on a init for an initramfs in C++ for Linux. This script is used to unlock the DM-Crypt w/ LUKS encrypted drive, and set the LVM drives to be available.
Since I don't want to have to reimplement the functionality of cryptsetup and gpg I am using system calls to call the executables. Using a system call to call gpg works fine if I have the system fully brought up already (I already have a bash script based initramfs that works fine in bringing it up, and I use grub to edit the command line to bring it up using the old initramfs). However, in the initramfs it never even acts like it gets called. Even commands like system("echo BLAH"); fail.
So, does anyone have any input?
Edit: So I figured out what was causing my errors. I have no clue as to why it would cause errors, but I found it.
In order to allow hotplugging, I needed to write /sbin/mdev to /proc/sys/kernel/hotplug...however I ended up switching around the parameters (on a function I wrote myself no less) so I was writing /proc/sys/kernel/hotplug to /sbin/mdev.
I have no clue as to why that would cause the problem, however it did.
Amardeep is right, system() on POSIX type systems runs the command through /bin/sh.
I doubt you actually have a legitimate need to invoke these programs you speak of through a Bourne shell. A good reason would be if you needed them to have the default set of environment variables, but since /etc/profile is probably also unavailable so early in the boot process, I don't see how that can be the case here.
Instead, use the standard fork()/exec() pattern:
int system_alternative(const char* pgm, char *const argv[])
{
pid_t pid = fork();
if (pid > 0) {
// We're the parent, so wait for child to finish
int status;
waitpid(pid, &status, 0);
return status;
}
else if (pid == 0) {
// We're the child, so run the specified program. Our exit status will
// be that of the child program unless the execv() syscall fails.
return execv(pgm, argv);
}
else {
// Something horrible happened, like system out of memory
return -1;
}
}
If you need to read stdout from the called process or send data to its stdin, you'll need to do some standard handle redirection via pipe() or dup2() in there.
You can learn all about this sort of thing in any good Unix programming book. I recommend Advanced Programming in the UNIX Environment by W. Richard Stevens. The second edition coauthored by Rago adds material to cover platforms that appeared since Stevens wrote the first edition, like Linux and OS X, but basics like this haven't changed since the original edition.
I believe the system() function executes your command in a shell. Is the shell executable mounted and available that early in your startup process? You might want to look into using fork() and execve().
EDIT: Be sure your cryptography tools are also on a mounted volume.
what do you have in initramfs ? You could do the following :
int main() {
return system("echo hello world");
}
And then strace it in an initscript like this :
strace -o myprog.log myprog
Look at the log once your system is booted