Skip to content

Commit

Permalink
Merge pull request i-pi#322 from lab-cosmo/feat/socket_prefix
Browse files Browse the repository at this point in the history
Added an option to override the default prefix for Unix sockets
  • Loading branch information
mahrossi authored May 16, 2024
2 parents 899834d + 94adf7b commit 198fd69
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 26 deletions.
5 changes: 4 additions & 1 deletion bin/i-pi
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def main(fn_input, options):
raise ImportError('Profiling requires the `yappi` package.')

# construct simulation based on input file
simulation = Simulation.load_from_xml(fn_input, request_banner=True, custom_verbosity=options.verbosity)
simulation = Simulation.load_from_xml(fn_input, request_banner=True, custom_verbosity=options.verbosity, sockets_prefix=options.sockets_prefix)

# run the simulation
simulation.run()
Expand Down Expand Up @@ -96,6 +96,9 @@ if __name__ == '__main__':
choices=['quiet', 'low', 'medium', 'high', 'debug'],
help='Define the verbosity level.')

parser.add_option('-S', '--sockets_prefix', dest='sockets_prefix', default=None,
help='Prefix for profiler files.')

options, args = parser.parse_args()

# make sure that we have exactly one input file and it exists
Expand Down
7 changes: 6 additions & 1 deletion docs/src/distributed.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,12 @@ client becomes a significant overhead for the calculation. UNIX-domain
sockets create a special file in the local file system, that serves as a
rendezvous point between server and clients, and are uniquely identified
by the name of the file itself, that can be specified in the “address”
tag of in the xml input file and in the input of the client.
tag of in the xml input file and in the input of the client. By default
this file is created based on the address tag, with a `/tmp/ipi_` prefix.
This can be overridden setting the “sockets_prefix” attribute for the
:ref:`simulation` tag in the input file, or on the command-line using the
`-S` option. Note that several clients do not support changing the default
prefix.

Unfortunately, UNIX sockets do not allow one to run i-PI and the clients
on different computers, which limits greatly their utility when one
Expand Down
13 changes: 9 additions & 4 deletions drivers/f90/driver.f90
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ PROGRAM DRIVER
! SOCKET VARIABLES
INTEGER, PARAMETER :: MSGLEN=12 ! length of the headers of the driver/wrapper communication protocol
INTEGER socket, inet, port ! socket ID & address of the server
CHARACTER(LEN=1024) :: host
CHARACTER(LEN=1024) :: host, sockets_prefix="/tmp/ipi_"

! COMMAND LINE PARSING
CHARACTER(LEN=1024) :: cmdbuffer
Expand Down Expand Up @@ -111,6 +111,8 @@ PROGRAM DRIVER
ccmd = 3
ELSEIF (cmdbuffer == "-o") THEN ! reads the parameters
ccmd = 4
ELSEIF (cmdbuffer == "-S") THEN ! reads the socket prefix
ccmd = 5
ELSEIF (cmdbuffer == "-v") THEN ! flag for verbose standard output
verbose = 1
ELSEIF (cmdbuffer == "-vv") THEN ! flag for verbose standard output
Expand Down Expand Up @@ -207,6 +209,8 @@ PROGRAM DRIVER
par_count = par_count + 1
ENDDO
READ(cmdbuffer(commas(par_count)+1:),*) vpars(par_count)
ELSEIF (ccmd == 5) THEN
sockets_prefix = trim(cmdbuffer)//achar(0)
ENDIF
ccmd = 0
ENDIF
Expand Down Expand Up @@ -471,7 +475,7 @@ PROGRAM DRIVER
ENDIF

! Calls the interface to the POSIX sockets library to open a communication channel
CALL open_socket(socket, inet, port, host)
CALL open_socket(socket, inet, port, host, sockets_prefix)
nat = -1
DO WHILE (.true.) ! Loops forever (or until the wrapper ends!)

Expand Down Expand Up @@ -1051,8 +1055,9 @@ PROGRAM DRIVER
CONTAINS
SUBROUTINE helpmessage
! Help banner
WRITE(*,*) " SYNTAX: driver.x [-u] -a address -p port -m [dummy|gas|lj|sg|harm|harm3d|morse|morsedia|zundel|qtip4pf|pswater|lepsm1|lepsm2|qtip4p-efield|eckart|ch4hcbe|ljpolymer|MB|doublewell|doublewell_1D|water_dip_pol|harmonic_bath|meanfield_bath|ljmix|qtip4pf-sr|qtip4pf-c-1|qtip4pf-c-2|qtip4pf-c-json|qtip4pf-c-1-delta|qtip4pf-c-2-delta|qtip4pf-c-json-delta]"
WRITE(*,*) " -o 'comma_separated_parameters' [-v] "

WRITE(*,*) " SYNTAX: driver.x [-u] -a address [-p port] -m [dummy|gas|lj|sg|harm|harm3d|morse|morsedia|zundel|qtip4pf|pswater|lepsm1|lepsm2|qtip4p-efield|eckart|ch4hcbe|ljpolymer|MB|doublewell|doublewell_1D|water_dip_pol|harmonic_bath|meanfield_bath|ljmix|qtip4pf-sr|qtip4pf-c-1|qtip4pf-c-2|qtip4pf-c-json|qtip4pf-c-1-delta|qtip4pf-c-2-delta|qtip4pf-c-json-delta]"
WRITE(*,*) " -o 'comma_separated_parameters' [-S sockets_prefix] [-v] "
WRITE(*,*) ""
WRITE(*,*) " For LJ potential use -o sigma,epsilon,cutoff "
WRITE(*,*) " For SG potential use -o cutoff "
Expand Down
12 changes: 7 additions & 5 deletions drivers/f90/fsockets.f90
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ SUBROUTINE c_sleep(seconds) bind(C, name="c_sleep")
REAL(C_DOUBLE), value :: seconds
END SUBROUTINE c_sleep

SUBROUTINE open_csocket(psockfd, inet, port, host) BIND(C, name="open_socket")
SUBROUTINE open_csocket(psockfd, inet, port, host, sockets_prefix) BIND(C, name="open_socket")
USE ISO_C_BINDING
INTEGER(KIND=C_INT) :: psockfd, inet, port
CHARACTER(KIND=C_CHAR), DIMENSION(*) :: host
CHARACTER(KIND=C_CHAR), DIMENSION(*) :: host, sockets_prefix

END SUBROUTINE open_csocket

Expand Down Expand Up @@ -90,15 +90,17 @@ SUBROUTINE f_sleep(sleep_seconds)
CALL c_sleep(sleep_seconds)
END SUBROUTINE

SUBROUTINE open_socket(psockfd, inet, port, host)
SUBROUTINE open_socket(psockfd, inet, port, host, sockets_prefix)
IMPLICIT NONE
INTEGER, INTENT(IN) :: inet, port
INTEGER, INTENT(OUT) :: psockfd
CHARACTER(LEN=1024), INTENT(IN) :: host
CHARACTER(LEN=1024), INTENT(IN) :: host, sockets_prefix
CHARACTER(LEN=1,KIND=C_CHAR) :: chost(1024)
CHARACTER(LEN=1,KIND=C_CHAR) :: csock(1024)

CALL fstr2cstr(host, chost)
CALL open_csocket(psockfd, inet, port, host)
CALL fstr2cstr(sockets_prefix, csock)
CALL open_csocket(psockfd, inet, port, chost, csock)
END SUBROUTINE

SUBROUTINE fstr2cstr(fstr, cstr, plen)
Expand Down
6 changes: 3 additions & 3 deletions drivers/f90/sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Can be linked to a FORTRAN code that does not support sockets natively.
#include <time.h>
#endif

void open_socket(int *psockfd, int* inet, int* port, const char* host)
void open_socket(int *psockfd, int* inet, int* port, const char* host, const char* sockets_prefix)
/* Opens a socket.
Note that fortran passes an extra argument for the string length, but this is
Expand Down Expand Up @@ -107,8 +107,8 @@ ignored here for C compatibility.
// fills up details of the socket addres
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sun_family = AF_UNIX;
strcpy(serv_addr.sun_path, "/tmp/ipi_");
strcpy(serv_addr.sun_path+9, host);
strcpy(serv_addr.sun_path, sockets_prefix);
strcpy(serv_addr.sun_path+strlen(sockets_prefix), host);
// creates a unix socket

// creates the socket
Expand Down
16 changes: 14 additions & 2 deletions drivers/py/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,19 @@ def Message(mystr):


def run_driver(
unix=False, address="", port=12345, driver=Dummy_driver(), f_verbose=False
unix=False,
address="",
port=12345,
driver=Dummy_driver(),
f_verbose=False,
sockets_prefix="/tmp/ipi_",
):
"""Minimal socket client for i-PI."""

# Opens a socket to i-PI
if unix:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/tmp/ipi_" + address)
sock.connect(sockets_prefix + address)
else:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# this reduces latency for the small messages passed by the i-PI protocol
Expand Down Expand Up @@ -181,6 +186,13 @@ def run_driver(
default="localhost",
help="Host name (for INET sockets) or name of the UNIX domain socket to connect to.",
)
parser.add_argument(
"-S",
"--sockets_prefix",
type=str,
default="/tmp/ipi_",
help="Prefix used for the unix domain sockets. Ignored when using TCP/IP sockets.",
)
parser.add_argument(
"-p",
"--port",
Expand Down
7 changes: 4 additions & 3 deletions examples/hpc_scripts/slurm_single_node/job_advanced.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ IPI_PATH=
## Input file
IPI_INPUT=input.xml

## Determines the address of the Unix-domain socket used in the input
IPI_ADDRESS=$(grep '<address>' $IPI_INPUT | sed 's/[^>]*>[[:space:]]*//; s/[[:space:]]*<.*//')

## Driver command
IPI_DRIVER="i-pi-driver -a slurm-one-node -m zundel -u -v"
IPI_DRIVER="i-pi-driver -a $IPI_ADDRESS -m zundel -u -v"
DRIVER_INPUT=driver.in # ignored for the example

## Determines the address of the Unix-domain socket used in the input
IPI_ADDRESS=$(grep '<address>' $IPI_INPUT | sed 's/[^>]*>[[:space:]]*//; s/[[:space:]]*<.*//')

## We create a UUID to make sure there are no name clashes with other processes,
## or with previous failed runs that left socket files behind
Expand Down
14 changes: 13 additions & 1 deletion ipi/engine/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ class Simulation:

@staticmethod
def load_from_xml(
fn_input, custom_verbosity=None, request_banner=False, read_only=False
fn_input,
custom_verbosity=None,
sockets_prefix=None,
request_banner=False,
read_only=False,
):
"""Load an XML input file and return a `Simulation` object.
Expand All @@ -69,6 +73,7 @@ def load_from_xml(
specified by the input file.
request_banner (bool): Whether to print the i-PI banner,
if verbosity is higher than 'quiet'.
sockets_prefix (str): Use the specified prefix for all Unix domain sockets.
"""

# parse the file
Expand All @@ -86,6 +91,11 @@ def load_from_xml(
custom_verbosity = input_simulation.verbosity.fetch()
input_simulation.verbosity.value = custom_verbosity

if sockets_prefix is None:
# Get from the input file
sockets_prefix = input_simulation.sockets_prefix.fetch()
input_simulation.sockets_prefix.value = sockets_prefix

# print banner if not suppressed and simulation verbose enough
if request_banner and input_simulation.verbosity.value != "quiet":
banner()
Expand Down Expand Up @@ -122,6 +132,7 @@ def __init__(
ttime=0,
threads=False,
safe_stride=1,
sockets_prefix="ipi_",
):
"""Initialises Simulation class.
Expand All @@ -145,6 +156,7 @@ def __init__(
self.mode = mode
self.threading = threads
self.safe_stride = safe_stride
self.sockets_prefix = sockets_prefix

self.syslist = syslist
for s in syslist:
Expand Down
17 changes: 16 additions & 1 deletion ipi/inputs/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ class InputSimulation(Input):
"help": "A format for all printed floats.",
},
),
"sockets_prefix": (
InputAttribute,
{
"dtype": str,
"default": "/tmp/ipi_",
"help": "A prefix prepended to the `address` value to form the UNIX-domain socket location.",
},
),
}

dynamic = {
Expand Down Expand Up @@ -197,6 +205,7 @@ def store(self, simul):

super(InputSimulation, self).store()

self.sockets_prefix.store(simul.sockets_prefix)
self.output.store(simul.outtemplate)
self.prng.store(simul.prng)
self.step.store(simul.step)
Expand Down Expand Up @@ -325,7 +334,12 @@ def fetch(self):
or k == "ffcavphsocket"
):
info(" # @simulation: Fetching" + k, verbosity.low)
fflist.append(v.fetch())
new_ff = v.fetch()
if k == "ffsocket":
# overrides ffsocket prefix
print("OVERRIDIGN , ", new_ff.socket.sockets_prefix)
new_ff.socket.sockets_prefix = self.sockets_prefix.fetch()
fflist.append(new_ff)

# this creates a simulation object which gathers all the little bits
import ipi.engine.simulation as esimulation # import here as otherwise this is the mother of all circular imports...
Expand All @@ -342,6 +356,7 @@ def fetch(self):
ttime=self.total_time.fetch(),
threads=self.threading.fetch(),
safe_stride=self.safe_stride.fetch(),
sockets_prefix=self.sockets_prefix.fetch(),
)

return rsim
9 changes: 6 additions & 3 deletions ipi/interfaces/sockets.py
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ def __init__(
match_mode="auto",
exit_on_disconnect=False,
max_workers=128,
sockets_prefix="/tmp/ipi_",
):
"""Initialises interface.
Expand All @@ -632,6 +633,8 @@ def __init__(
self.slots = slots
self.mode = mode
self.timeout = timeout
self.sockets_prefix = sockets_prefix
print(f"#### {self.sockets_prefix}")
self.poll_iter = UPDATEFREQ # triggers pool_update at first poll
self.prlist = [] # list of pending requests
self.match_mode = match_mode # heuristics to match jobs and active clients
Expand All @@ -650,14 +653,14 @@ def open(self):
if self.mode == "unix":
self.server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
self.server.bind("/tmp/ipi_" + self.address)
self.server.bind(self.sockets_prefix + self.address)
info(
"Created unix socket with address " + self.address, verbosity.medium
)
except socket.error:
raise RuntimeError(
"Error opening unix socket. Check if a file "
+ ("/tmp/ipi_" + self.address)
+ (self.sockets_prefix + self.address)
+ " exists, and remove it if unused."
)

Expand Down Expand Up @@ -720,7 +723,7 @@ def close(self):
verbosity.low,
)
if self.mode == "unix":
os.unlink("/tmp/ipi_" + self.address)
os.unlink(self.sockets_prefix + self.address)

def poll(self):
"""Called in the main thread loop.
Expand Down
7 changes: 5 additions & 2 deletions ipi/utils/inputvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -828,12 +828,15 @@ def help_rst(self, name="", indent="", level=0, stop_level=None, standalone=True
# For classes such as InputCell, self._default is not the value,
# instead it is an object that is stored, putting the default value in
# self.value. For this reason we print out self.value at this stage,
# and not self._default
# and not self._default. We also escape underscores that might appear
# in the default string value.
rstr += (
"\n"
+ indent
+ "*default*: "
+ self.pprint(self.value, indent=indent, latex=False)
+ self.pprint(self.value, indent=indent, latex=False).replace(
"_", r"\_"
)
+ "\n"
)

Expand Down

0 comments on commit 198fd69

Please sign in to comment.