writing to text file in MPI - c

I'm trying to write to text file with MPI but the file is not created.
I need only to write at the master (rank = 0), but nothing works.
It only working when I running the program in console (and save corrupt element) and not in Mpich2 and
I attached the code.
Thanks for helping.
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
* (C) 2001 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
/* This is an interactive version of cpi */
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int namelen, numprocs, rank;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Get_processor_name(processor_name,&namelen);
MPI_Status status;
FILE* f = fopen("test.txt","wb+");
if (rank == 0) {
for (int i=0; i < 5; i++){
fprintf(f,"%d \n",i);
}
fclose(f);
}
else {
// do nothing
}
MPI_Finalize();
return 0;
}

In the sample code you posted, all processes open the file and only process 0 closes it. Could you try the following modification ?
if (rank == 0) {
FILE* f = fopen("test.txt","wb+");
if(f==NULL){printf("failed to open file: permission issue ?\n");exit(1);}
for (int i=0; i < 5; i++){
fprintf(f,"%d \n",i);
}
fclose(f);
}
Since your code seems to come from the Argonne National Laboratory, I suppose that it is ran on a cluster using a particular file system.
The following code is based on yours. It makes use of MPI_File_open() and MPI_File_write() on a single process, using MPI_COMM_SELF.
/* This is an interactive version of cpi */
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char *argv[])
{
int namelen, numprocs, rank;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Get_processor_name(processor_name,&namelen);
MPI_Status status;
MPI_File fh;
if (rank == 0) {
MPI_File_open(MPI_COMM_SELF, "test.txt",MPI_MODE_CREATE | MPI_MODE_WRONLY,MPI_INFO_NULL,&fh);
//FILE* f = fopen("test.txt","wb+");
//if(f==NULL){
//printf("failed to open file\n");exit(1);
//}
for (int i=0; i < 5; i++){
char buf[42];
//fprintf(f,"%d \n",i);
snprintf(buf,42,"%d \n",i);
MPI_File_write(fh,buf,strlen(buf), MPI_CHAR,&status);
}
// fclose(f);
MPI_File_close(&fh);
}
else {
// do nothing
}
MPI_Finalize();
return 0;
}
Please make sure that you hae the permission to write in the considered folder. Make sure that all nodes can access this folder ! Try some folders like your folder in /tmp or /scratch... Your cluster may have some sort of documentation somewhere telling you where you can write files !

Related

Error when changing the console output to file in C

I'm new to stack overflow so bear with me :)
I am trying to create a custom linux shell as a project.
Right now I want to make the default output going to a file instead of console when the user uses > symbol for example ls > filename.txt
But , the program crashes and a Bad address error pops yet it writes the command output to the file.
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
typedef char* string;
int main (int argc,char** argv) {
int error = 0;
int posIn=0; int posOut=0; int appendMark=0;
string Output,Input;
while (1) {
error=0;
char progName[255];
printf("\nmysh3 > ");
if(fgets(progName,500,stdin)==NULL){return 0 ;}
char dir[1024];
string params[40];
string pch=progName;
int i=0;
while ((pch = strtok (pch," \n")) != NULL){
params[i]=pch;
if (strcmp(pch,"<")==0) { posIn = i;params[i]=NULL;i--;} // < is skipped and we put only the name of the command on the params array
if (strcmp(pch,">")==0) { posOut = i;params[i]=NULL;i--;} //output
if (strcmp(pch,">>")==0) {appendMark=1;params[i]=NULL;i--;}
i++;
pch = NULL;
}
params[i]=NULL;
if(strlen(progName)>255){
printf("The commands can't be over 255 characters\n");
return 0;
}
if (posOut) {
int out = open(params[posOut], O_CREAT|O_TRUNC|O_WRONLY, 0777);
params[posOut]=NULL;
if (out < 0) {
error = 1;
fprintf(stderr,"open error: %d [%s]\n",errno,strerror(errno));
exit(1); }
int k = dup2(out,1);
if (k<0) {
error = 1;
perror("Cannot redirect output");
}
close(out);
}
pid_t proccess1,waitpid;
int status;
proccess1 = fork();
if (proccess1<0) {perror("Out of memory"); } //Monos tropos na apotyxei h fork einai na mhn yparxei mnhmh
else if (proccess1==0) {
execvp(params[0],params);
if (!error) {perror("Unknown command");}
}
else {
waitpid=wait(&status);
if (waitpid==-1) {perror("ERROR: A NEW ZOMBIE IS BORN 3:)");return 0;}
}
}
return 0; }

client/server print out array and write back

I am using C and putty to write a client/server program.
Both c files are on the same system.
I am currently having an issue with writing back to the client the frames it is using as well as printing out my frames. It prints out 3 0 9 8 but then it starts printing out 13456756 etc.
Here is what I have:
server:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
main (void)
{
int to_server; // to read from client
int from_server; // to write to client
int finish; // lets me know that client is done
int i,j,k,m,l; // because C needs this defined as int
int numClient;// number of clients
char temp[14];
int page_size = 128;
int pages_left;
int max_frames=10;
int used_frames =0;
int frameUpdate=0;
int freeframe[10] = {3,0,9,8,7,5,1,4,2,6}; //this is the array
int numpage=0;
int frames;
int check;
int option;
int byte;
int getPage;
int getOffset;
int physical_Addr;
int offset;
int req[3];
int again;
struct values{
char privFifo[14];
int memoryreq;
}cinput;
/* Create the fifos and open them */
if ((mkfifo("FIFO1",0666)<0 && errno != EEXIST))
{
perror("cant create FIFO1");
exit(-1);
}
if((to_server=open("FIFO1", O_RDONLY))<0){
printf("cant open fifo to write");
}
//get number of clients
printf("\nHow many clients?\n");
scanf("%d", &numClient);
for(j =1; j <= numClient; j++){
read(to_server, &cinput, sizeof(cinput));
printf("\n\nFifo_%d \nMemory request %d", &cinput.privFifo, cinput.memoryreq);
req[j-1] = cinput.memoryreq;
if((mkfifo(cinput.privFifo,0666)<0 && errno != EEXIST))
{
perror("cant create privFifo");
exit(-1);
}
if((from_server=open(cinput.privFifo, O_WRONLY)<0)){
printf("cant open fifo to write");
}
// find number of pages need for request
numpage = cinput.memoryreq/page_size;
if((numpage * page_size) < cinput.memoryreq){
numpage++;
}
sleep(1);
printf("\nPages needed %d", numpage);
write(from_server, &numpage, sizeof(numpage));
printf("\n******Main Memory******");
for(m = used_frames; m < numpage; m++){
printf("\n* client: %d\tframe: %d", j, freeframe[m]);
frames = freeframe[m];
write(from_server, &frames, sizeof(frames));
}
used_frames = max_frames - used_frames;
pages_left = max_frames - numpage;
//this is where I try to print out the available frames
printf("\n Frames available:");
for(l = pages_left; l!= 0; l--){
check = max_frames - l;
printf(" %d", freeframe[check]);
max_frames = check;
}
close(from_server);
unlink(cinput.privFifo);
}
printf("\nDONE!!!");
close(to_server);
unlink("FIFO1");
client:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
main (void)
{
int to_server; // to write to server
int from_server;
char temp[14]; // server puts string here
int clientID;
//int frames;
int numpage;
int i;
struct values{
char privFifo[14];
int memoryreq;
}cinput;
if((to_server=open("FIFO1", O_WRONLY))<0)
printf("cant open fifo to write\n");
printf("writing data to to_server\n");
printf("Client: Please enter number of memory units: ");
scanf("%d", &cinput.memoryreq);
printf("%d", cinput.memoryreq);
clientID = getpid();
sprintf(cinput.privFifo, "Fifo_%d", getpid());
printf("\nFifo name is %s", &cinput.privFifo);
write(to_server, &cinput, sizeof(cinput));//write client pid and memUnit to server
sleep(2); //give time to send
printf("\nClient: Got the character sent, now waiting for response ");
if ((mkfifo(cinput.privFifo,0666)<0 && errno != EEXIST))
{
perror("cant create FIFO1");
exit(-1);
}
if((from_server=open(cinput.privFifo, O_RDONLY))<0){
printf("cant open fifo to write");
}
read(from_server, &numpage, sizeof(numpage));
printf("\nFrames Occupied %d", numpage);
close(to_server);
close (from_server);
unlink(cinput.privFifo);
printf ("\nall done!\n");
}
Any help is greatly appreciated. Thank you.
I strongly suspect the problem is the line used_frames = max_frames - used_frames;. Since used_frames is initially 0, that sets it one past the end of the array for the second iteration, so you start printing values past the end of your frame array when you run for(m = used_frames; m < numpage; m++). (By the way: please indent properly.). But set a breakpoint and run in a debugger to be sure.

MPI and C: loop through file of commands in file

Hi I want to parallelize a process on 40 cpus, where each job runs 1 process.
I am using C and MPI with the TORQUE (PBS) scheduler on my cluster.
Here is my script.
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <unistd.h>
const char FILE_NAME[] = "/home/foo/c/mpi/cov_test/test_command.txt";
const char WRK_DIR[] = "/home/foo/c/mpi/cov_test";
char comm[39][256];
int main(int argc, char **argv)
{
int rank;
int size;
int count =0;
FILE *in_file;
char line[256];
char *pos;
in_file = fopen(FILE_NAME, "r");
if (in_file == NULL) {
printf("Cannot open %s\n", FILE_NAME);
exit(8);
}
if(in_file)
{
while(fgets(line, sizeof(line), in_file))
{ /* Remove newline at end of file *
* Maybe not the best way to do it? *
* mpicc compiler throws an error */
if((pos=strchr(line, '\n')) != NULL)
*pos = '\0';
strcpy(comm[count], line);
count++;
}
}
chdir(WRK_DIR);
chdir(WRK_DIR);
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
/* Saw this on another SO posting */
int start = (rank*count)/size;
int end = ((rank+1)*count)/size;
for(int i= start; i < end; i++) {
printf("%s\n", comm[rank]);
/*system(comm[rank]);*/
}
MPI_Finalize();
}
The output i only the first command of the file "test_command.txt"
Here is my Torque submission file
#!/bin/bash
#PBS -q condo
#PBS -l walltime=01:00:00
#PBS -l nodes=5:ppn=8
#PBS -j oe
#PBS -o /home/foo/c/mpi/cov_test/pilot_mpi_out
#had to export my perl libraries
export PERL5LIB=/home/foo/myperl/lib/perl5:/home/foo/myperl/share/perl5:$PERL5LIB
cd $HOME/c/mpi/cov_test
/opt/openmpi/bin/mpirun -machinefile $PBS_NODEFILE -np 40 ./pilot_mpi_test-2
I'm new to C so I might be (probably) doing something ghastly. Thanks for your time :)
It should be printf("%s\n", comm[i]); instead of printf("%s\n", comm[rank]);.
From what I understand you are getting a single line of output when you expect 40. You may want to verify that you are getting output from processes other than process 0. I would add a
printf("Processes %d\n", rank);
just after the MPI_Comm_size line. If you don't see a line from each process something will need changed in your environment. I did a little looking but my GoogleFu has been failing me this morning. The other option is to pass the strings back to process 0 with MPI.

Zombie process - Finding it

I used inotify() function in my program to monitor /proc directory. Now my job is to find when a process become zombie. Then i need output a warning that zombie process was found. At the moment program is recording some of the changes but i don't know how to find zombie process..
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/inotify.h>
#include <limits.h>
int main()
{
int inotify_fd, wd;
int num;
char buffer[sizeof(struct inotify_event)+NAME_MAX+1];
struct inotify_event *dogodek;
inotify_fd = inotify_init();
if (inotify_fd==-1) {
perror("inotify_init");
return 1;
}
wd = inotify_add_watch(inotify_fd, "/proc/",IN_ALL_EVENTS);
if (wd==-1) {
perror("inotify_add_watch");
return 1;
}
printf("Map gots descriptor %d\n",wd);
int f;
for (f=0; f<20; f++) {
num=read(inotify_fd, &buffer, sizeof(buffer));
if (num>0) {
dogodek=(struct inotify_event*)buffer;
printf("Access to map with descriptor %d\n", dogodek->wd);
if (dogodek->len>0)
printf("\tevent found: %s\n", dogodek->name);
else
printf("\tevent found in directory!\n");
printf("\tMask of the event %x\n", dogodek->mask);
if (dogodek->mask & IN_ACCESS)
printf("\t\tReading file!\n");
if (dogodek->mask & IN_CREATE)
printf("\t\tCreating file!\n");
if (dogodek->mask & IN_DELETE)
printf("\t\tDeleting file!\n");
if (dogodek->mask & IN_OPEN)
printf("\t\tOpening file!\n");
}
}
inotify_rm_watch(inotify_fd, wd);
return 0;
}
I need example in code not just explation if there is a possibility.
The following applies to Linux (at least):
The status of a process can be found in /proc/[pid]/status.
For a zombie the file /proc/[pid]/cmdline is empty, that is reading from it returns 0 bytes.
For details please see here: http://man7.org/linux/man-pages/man5/proc.5.html

Force MPI_Send to use eager or rendezvouz protocol

I'm doing a little MPI (openmpi) program in C for a workshop at college. Our objective is to observe the time difference between the two main protocols of MPI, eager and rendezvous, regarding the message size.
We haven't worked with MPI before, and we have thought that there may be a way to "select" between the two protocols. Searching on google for information about how to do it I found (somewhere I don't remember) that there is an eager limit. I read that it is set by the MPI implementation, and also, that you can change it somehow.
Any advice on how to choose between the protocols?
Are there any relation between the protocols and MPI_Send/MPI_Isend?
I thought that changing the receiver buffer size will break from eager and start using rendezvous. But it's just a hunch.
Here is my code for now:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "mpi.h"
#define KBdata 32000 //openmpi default buffer size
#define ndata KBdata/4 //number of ints that fits in buffer
int main(int argc, char *argv[]) {
int myid, numprocs;
int tag,source,destination,count;
int buffer[ndata];
MPI_Status status;
MPI_Request request;
int iter = 20;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
if (myid == 0 && numprocs == 2) { //to
int recvID = 1;
double acum = 0;
int i;
double startT;
for (i=0;i<iter;++i)
{
double startTime = MPI_Wtime();
MPI_Send(&buffer,ndata,MPI_INT,recvID,0,MPI_COMM_WORLD);
double endTime = MPI_Wtime();
double elapsed = endTime - startTime;
acum += elapsed;
printf("%d, %f, elapsed: %f\n",i,acum,elapsed);fflush(stdout);
usleep(500000);
}
printf("total: %f\nmean: %f\n", acum, acum/iter);
}
else if (numprocs == 2) {
int i;
for(i=0; i<iter; ++i)
{
printf("Waiting for receive\n");fflush(stdout);
MPI_Recv(&buffer,ndata,MPI_INT,0,0,MPI_COMM_WORLD,&status);
printf("Received %d\n",i);fflush(stdout);
}
}
else {
printf("Need only 2 threads\n");
}
MPI_Finalize();
return 0;
}
Thank you in advice.
There is no direct connection between eager/rendezvous and MPI_Send/Isend. However, if you're under the eager limit, your MPI_Send is no longer blocking. If you want it to block regardless, you can use MPI_Ssend.
Regarding eager limits:
MVAPICH2:
MV2_IBA_EAGER_THRESHOLD= < nbytes >
Intel MPI (depending on version):
I_MPI_EAGER_THRESHOLD= < nbytes >
I_MPI_SHM_EAGER_THRESHOLD= < nbytes >
Open MPI:
--mca_btl_openib_eager_limit < nbytes >
--mca_btl_openib_rndv_eager_limit < nbytes >
Cray MPICH:
MPICH_GNI_MAX_EAGER_MSG_SIZE=<value>

Resources