Sziasztok!
Egy erdekes problema a kovetkezo (a topic nem utal halozatra, de majd megiscsak fog): van egy gep, van benne manapsag mar tobb proci (vagyis tobb mag, de persze lehet tobb proci is). Ezt hasznaljuk adatfeldolgozasra: egy nagy file diszkrol beolvas, sokaig csamcsog, valami adat (kisebb-nagyobb file) kiir; es ez jol parhuzamosithato mert a fileok egymastol teljesen fuggetlenul feldolgozhatoak. A tapasztalat az, hogyha egyszerre sok proci nekiesik parhuzamosan a problemanak, akkor -- mivel a fileok ugyanazon a diszken vannak -- nagyon-nagyon leesik a hatekonysag, foleg akkor, ha a partico NFS-en keresztul fel van masik gepre mount-olva, gyakorlatialg nagysagrenddel lassabb, mintha szekvencialisan olvasna. Az NFS az tenyleg vad, nem mondom hogy hasznalhatatlan, de nagyon tud blokkolni. Gyakorlatban ~50-100 megas fileok i/o-jarol van szo, gigabites ethernet, ~100-200mega/sec-es diszk i/o (hw raid) 4-6 gep es osszesen kb. 30-40 proci/mag (a gepek kozott van sima ketmagos, dual ketmagos, quad ketmagos, 2 x quad ketmagos, elegge vegyes allatkert).
Kerdes, hogy letezik-e erre a problemara valami mutex-szeru" ke'sz megoldas, amire azt mondom, hogy egy adott backend filerendszert mondjuk N-en (N=1 vagy max 2) hasznalhatnak, es egy sima kis progi blokkol, ameddig valaki fogja a filerendszert? Persze nem feltetlenul ennyire trivialis a problema, mert lehet hogy egy file-t egyetlen stock binaris dolgoz fel (es akkor nyilvan vagy nagyon bele kell turni a programba). De egy ilyesmit el tudok kepzelni:
( fsmutex --lock ; cat $bemenet.dat ; fsmutex --unlock ) | nagybonyaprogram >$kimenet.dat
(mondjuk ebben a peldaban a
$kimenet.dat
kicsi/elhanyagolhato meretu", de a $bemenet.dat nem)
Udv, A.
- 968 megtekintés
Hozzászólások
up
- A hozzászóláshoz be kell jelentkezni
procmail-lel együtt jár egy lockfile nevű program, továbbá van egy lockfile-progs csomag is.
- A hozzászóláshoz be kell jelentkezni
Erdekesnek tunik, de nem pollozhato, emiatt produktive nem hiszem hogy nagyon jol hasznalhato lenne (ti. sleep()-pel var: ha tul nagy az ido", akkor pang a rendszer, ha tul kicsi, akkor nagy az overhead, egyszeruen arra megy el a cpu es/vagy diszkio hogy file-okat probal letrehozni).
- A hozzászóláshoz be kell jelentkezni
Ahán. Akkor a lockolós utilnak meg kell mondani, hogy csak egyszer próbálkozzon, és ha a próbálkozás sikertelen, akkor inotifywait-tel (inotify-tools csomag) várakozni a lockfile-ra.
- A hozzászóláshoz be kell jelentkezni
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED 1
#include <errno.h> /* errno */
#include <limits.h> /* SHRT_MIN */
#include <stdio.h> /* fprintf() */
#include <stdlib.h> /* EXIT_FAILURE */
#include <string.h> /* strrchr */
#include <sys/ipc.h> /* ftok() */
#include <sys/sem.h> /* semget() */
#include <sys/stat.h> /* S_IRUSR */
static const char *pname;
static key_t
x_ftok(const char *pathname, int proj_id)
{
key_t key = ftok(pathname, proj_id);
if ((key_t)-1 == key) {
(void)fprintf(stderr, "%s: ftok(): %s\n", pname, strerror(errno));
exit(EXIT_FAILURE);
}
return key;
}
static int
x_semget(key_t key)
{
int semid = semget(key, 1, 0);
if (-1 == semid) {
(void)fprintf(stderr, "%s: semget(): %s\n", pname, strerror(errno));
exit(EXIT_FAILURE);
}
return semid;
}
static void
x_semcreat(key_t key, int initval)
{
int semid = semget(key, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
if (-1 == semid)
(void)fprintf(stderr, "%s: semget(IPC_CREAT | IPC_EXCL): %s\n", pname,
strerror(errno));
else {
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
} arg;
arg.val = initval;
if (0 == semctl(semid, 0, SETVAL, arg)) {
(void)fprintf(stderr, "%s: initialized semid %d\n", pname, semid);
return;
}
(void)fprintf(stderr, "%s: semctl(SETVAL): %s\n", pname, strerror(errno));
if (-1 == semctl(semid, 0, IPC_RMID))
(void)fprintf(stderr, "%s: semctl(%d, IPC_RMID): %s\n", pname,
semid, strerror(errno));
}
exit(EXIT_FAILURE);
}
static void
x_semadd(int semid, short incr)
{
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = incr;
buf.sem_flg = 0;
if (-1 == semop(semid, &buf, 1)) {
(void)fprintf(stderr, "%s: semop(): %s\n", pname, strerror(errno));
exit(EXIT_FAILURE);
}
}
static long
x_long(const char *str, const char *desc, long min, long max)
{
long ret;
char *endptr;
errno = 0;
ret = strtol(str, &endptr, 0);
if (0 != errno || '\0' == *str || '\0' != *endptr
|| min > ret || max < ret) {
(void)fprintf(stderr, "%1$s: failed to parse \"%2$s\" as %3$s or"
" %3$s not in range [%4$ld .. %5$ld]\n", pname, str, desc, min, max);
exit(EXIT_FAILURE);
}
return ret;
}
int
main(int argc, char **argv)
{
pname = strrchr(argv[0], '/');
pname = pname ? pname + 1 : argv[0];
if (2 == argc && 0 == strcmp(argv[1], "help"))
(void)fprintf(stderr,
"%1$s: perform basic semaphore operations\n"
"Copyright (C) 2007 lacos, GNU GPLv2+\n"
"%2$s\n"
"\n"
"usage: \n"
"%1$s help - print this help and exit successfully\n"
"%1$s create PATHNAME PROJ_ID INITVAL - create new semaphore\n"
"%1$s op PATHNAME PROJ_ID DIFF - modify existing semaphore\n",
pname, "$Id: sem.c,v 1.2 2007/11/15 23:29:44 lacos Exp $");
else
if (5 == argc && 0 == strcmp(argv[1], "create"))
x_semcreat(
x_ftok(
argv[2],
x_long(argv[3], "PROJ_ID", 1, 255)
),
x_long(argv[4], "INITVAL", 0, INT_MAX)
);
else
if (5 == argc && 0 == strcmp(argv[1], "op"))
x_semadd(
x_semget(
x_ftok(
argv[2],
x_long(argv[3], "PROJ_ID", 1, 255)
)
),
x_long(argv[4], "DIFF", SHRT_MIN, SHRT_MAX)
);
else {
(void)fprintf(stderr, "%1$s: invalid parameters, run \"%1$s help\""
" for help\n", pname);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
A fenti példádban az
fsmutex --lock
-ot cseréld ki például
ssh fileserver sem op / 1 -1
-re, az
fsmutex --unlock
-ot pedig cseréld ki
ssh fileserver sem op / 1 +1
-re. Az egész előtt egyszer hozd létre / inicializáld a szemafort (pontosabban: egyelemű szemafortömböt):
ssh fileserver sem create / 1 2
(ha egyszerre legfeljebb kettőt akarsz tudni futtatni).
A
PATHNAME
és
PROJ_ID
jelentéséhez az
ftok()
man-ját ajánlom. (Annak is különösen az ütközésekre vonatkozó részét.) Szerintem maradj egy megbízható file-nál (pl.
/
), és a
PROJ_ID
-vel variálj, ha szükséges. Esetleg a "zárolni kívánt" filerendszer mount-point-ját add meg mindig
PATHNAME
-ként, és a
PROJ_ID
legyen 1.
Ajánlom még:
ipcs
,
ipcrm -s
.
Az inicializációnál a program kiírja a szemafor(tömb) azonosítóját, hogy az
ipcrm -s
-sel könnyen kiirthasd, ha akarod. Mivel az inicializáció két lépésből áll (létrehozás, érték beállítása), azért ha a második lépés bedöglik (próbáld meg 32768-cal pl.), "visszavonja" az elsőt is. Ha ez a visszavonás nem sikerül neki, akkor is megmondja az azonosítót, hátha te majd tudod törölni.
Az ssh-val belépegetés nem valami tetszetős, de így bármilyen shell script-ből lehet használni (helyileg is), illetve azt mondtad, hogy a file-ok jó sok megásak, ill. a kliensen a számolgatás CPU-igényes, úgyhogy azok mellett az ssh el fog törpülni. A szerveren az sshd-nek valóban több dolga lesz egy kicsit.
Kiegészítés: a down-ok és up-ok szétcsúszásának valószínűségét csökkentendő, a program köré a shell script-et valahogy így érdemes kanyarítani:
#!/bin/bash
set -e -C
PATHNAME=...
PROJ_ID=...
INPUT=...
OUTPUT=...
ssh fileserver sem op "$PATHNAME" "$PROJ_ID" -1
trap 'ssh fileserver sem op "$PATHNAME" "$PROJ_ID" +1' EXIT
work <"$INPUT" >"$OUTPUT"
- A hozzászóláshoz be kell jelentkezni
Koszi, ezt a megoldast fontolora veszem. Egyelore egy cel-demont probalok osszedobni, ami az egesz parhuzamositott futtatast osszefogja es ez fogja kezelni a mutex-eket is. Maga a demon megcsinalja a tunnelt a gepek kozott, igy a mutex-hivasokat nem kell ssh-n keresztul meg extra modon atvinni, hanem mehetnek localhoston is, illetve igy egy "lockable cat" is egyszerubben implementalhato. Par nap, es szerintem fel is teszem valahova a produktumot, hha mast is erdekel.
- A hozzászóláshoz be kell jelentkezni