最近很多小伙伴都在问如何与子进程共享父进程的numpy随机状态?和子进程和父进程不共享地址空间这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展ACL编程之父子进程机制,父进程守护子
最近很多小伙伴都在问如何与子进程共享父进程的numpy随机状态?和子进程和父进程不共享地址空间这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展ACL编程之父子进程机制,父进程守护子进程以防止子进程异常退出、activemq所在的java进程如果启动子进程,该父进程重启后与之前的connection都失连,经定位,发现父进程关闭后,子进程中发生阻塞、linux fork 父子进程共享指针、linux – 使用SIGKILL杀死父进程和子进程等相关知识,下面开始了哦!
本文目录一览:- 如何与子进程共享父进程的numpy随机状态?(子进程和父进程不共享地址空间)
- ACL编程之父子进程机制,父进程守护子进程以防止子进程异常退出
- activemq所在的java进程如果启动子进程,该父进程重启后与之前的connection都失连,经定位,发现父进程关闭后,子进程中发生阻塞
- linux fork 父子进程共享指针
- linux – 使用SIGKILL杀死父进程和子进程
如何与子进程共享父进程的numpy随机状态?(子进程和父进程不共享地址空间)
我在程序开始时设置了numpy随机种子。在程序执行期间,我使用多次运行一个函数multiprocessing.Process
。该函数使用numpy随机函数绘制随机数。问题是Process
获取当前环境的副本。因此,每个进程都独立运行,并且都以与父环境相同的随机种子开始。
所以我的问题是如何在父环境中与子进程环境共享numpy的随机状态?请注意,我想Process
用于自己的工作,需要使用一个 单独的类
并importnumpy
在该类中单独进行操作。我尝试使用multiprocessing.Manager
来共享随机状态,但是似乎事情没有按预期进行,并且我总是得到相同的结果。同样,将for循环移入内部drawNumpySamples
还是保留在循环中都没有关系main.py
。我仍然无法获得不同的数字,并且随机状态始终相同。这是我的代码的简化版本:
# randomClass.pyimport numpy as npclass myClass(self): def __init__(self, randomSt): print (''setup the object'') np.random.set_state(randomSt) def drawNumpySamples(self, idx) np.random.uniform()
并在主文件中:
# main.py import numpy as np from multiprocessing import Process, Manager from randomClass import myClass np.random.seed(1) # set random seed mng = Manager() randomState = mng.list(np.random.get_state()) myC = myClass(randomSt = randomState) for i in range(10): myC.drawNumpySamples() # this will always return the same results
注意 :我使用Python
3.5。我还在Numpy的GitHub页面上发布了一个问题。只需在此处发送问题链接以供将来参考。
答案1
小编典典即使您设法做到这一点,我也不认为它会做您想要的。一旦有多个进程并行地从同一个随机状态中拉出,就不再确定它们各自到达状态的顺序,这意味着您的运行实际上不会重复。可能有一些解决方法,但这似乎是一个不小的问题。
同时,有一个解决方案应同时解决您想要的问题和不确定性问题:
在生成子进程之前,请向RNG询问随机数,并将其传递给子进程。然后,孩子可以用该数字播种。然后,每个子代将具有与其他子代不同的随机序列,但是如果您使用固定种子重新运行整个应用程序,则每个子代将具有与同一子代相同的随机序列。
如果您的主流程执行了可能不确定地依赖于子流程执行的任何其他RNG工作,那么您将需要在提取任何其他随机数之前按顺序为所有子流程预先生成种子。
正如senderle在评论中指出的那样:如果您不需要多次不同的运行,而只需要进行一次固定运行,则甚至不需要从已播种的RNG中提取种子。只需使用一个从1开始的计数器,并为每个新进程递增它,并将其用作种子即可。我不知道这是否可以接受,但是如果可以接受,很难比这更简单。
正如Amir在评论中指出的那样:一种更好的方法是每次生成新进程时都绘制一个随机整数,并将该随机整数传递给新进程,以使用该整数设置numpy的随机种子。这个整数确实可以来自np.random.randint()
。
ACL编程之父子进程机制,父进程守护子进程以防止子进程异常退出
在WIN32平台进行编程时,经常会遇到工作进程因为程序内部BUG而异常退出的现象,当然为了解决此类问题最好还是找到问题所在并解决它,但如果这类导致程序崩溃的BUG并不是经常出现,只有当某种条件发生时才会有,在我们解决BUG的时间里,为了尽最大可能地为用户提供服务可以采用一种父进程守护机制:当子进程异常退出时,守护父进程可以截获这一消息,并立即重启子进程,这样用户就可以继续使用我们的程序了,当然如果子进程的问题比较严重频繁地 DOWN掉,而父进程却不停地重启子进程的话,势必造成用户机系统资源的大量耗费,那我们的程序就如病毒一样,很快耗尽了用户机资源,所以需要父进程能够智能地控制重启子进程的时间间隔。
本文将给出一个具体的例子(利用ACL库),介绍父、子进程的编程方法。
一、接口介绍
1.1 以守护进程方式运行的接口
创建守护进程的方式非常简单,只需要调用 acl_proctl_deamon_init, acl_proctl_daemon_loop 两个函数即可
接口说明如下:
/**
* 初始化进程控制框架(仅 acl_proctl_start 需要)
* @param progname {const char*} 控制进程进程名
*/
ACL_API void acl_proctl_deamon_init(const char *progname);
/**
* 控制进程作为后台服务进程运行,监视所有子进程的运行状态,
* 如果子进程异常退出则会重启该子进程
*/
ACL_API void acl_proctl_daemon_loop(void);
1.2 以命令方式来控制守护进程(守护进程即控制进程的意思)
守护进程启动后,可以以命令方式控制守护进程来启动、停止子进程,或查询显示当前正在运行的子进程。
启动子进程:acl_proctl_start_one
停止子进程:acl_proctl_stop_one
停止所有子进程:acl_proctl_stop_all
查询子进程是否在运行:acl_proctl_probe
查询当前所有在运行的子进程:acl_proctl_list
通过守护进程停止所有子进程且守护进程自身退出:acl_proctl_quit
接口说明如下:
/**
* 以命令方式启动某个子进程
* @param progname {const char*} 控制进程进程名
* @param progchild {const char*} 子进程进程名
* @param argc {int} argv 数组的长度
* @param argv {char* []} 传递给子进程的参数
*/
ACL_API void acl_proctl_start_one(const char *progname,
const char *progchild, int argc, char *argv[]);
/**
* 以命令方式停止某个子进程
* @param progname {const char*} 控制进程进程名
* @param progchild {const char*} 子进程进程名
* @param argc {int} argv 数组的长度
* @param argv {char* []} 传递给子进程的参数
*/
ACL_API void acl_proctl_stop_one(const char *progname,
const char *progchild, int argc, char *argv[]);
/**
* 以命令方式停止所有的子进程
* @param progname {const char*} 控制进程进程名
*/
ACL_API void acl_proctl_stop_all(const char *progname);
/**
* 探测某个服务进程是否在运行
* @param progname {const char*} 控制进程进程名
* @param progchild {const char*} 子进程进程名
*/
ACL_API void acl_proctl_probe(const char *progname, const char *progchild);
/**
* 列出当前所有正在运行的服务进程
* @param progname {const char*} 控制进程进程名
*/
ACL_API void acl_proctl_list(const char *progname);
/**
* 以命令方式通知控制进程停止所有的子进程,并在子进程退出后控制进程也自动退出
* @param progname {const char*} 控制进程进程名
*/
ACL_API void acl_proctl_quit(const char *progname);
1.3、子进程编写
子进程编程也比较容易,只需在程序初始化时调用 acl_proctl_child 即可,这样子进程就会在硬盘创建自己的信息并与父进程(即守护进程)建立联系。
接口说明:
/**
* 子进程调用接口,通过此接口与父进程之间建立控制/被控制关系
* @param progname {const char*} 子进程进程名
* @param onexit_fn {void (*)(void*)} 如果非空则当子进程退出时调用的回调函数
* @param arg {void*} onexit_fn 参数之一
*/
ACL_API void acl_proctl_child(const char *progname, void (*onexit_fn)(void *), void *arg);
二、例子
2.1、父进程
程序名:acl_project\samples\proctl\proctld.cpp
// proctld.cpp : 定义控制台应用程序的入口点。
//
#pragma comment(lib,"ws2_32")
#include "lib_acl.h"
#include <assert.h>
static void init(void)
{
acl_init(); // 初始化ACL库
}
static void usage(const char *progname)
{
printf("usage: %s -h [help] -d [START|STOP|QUIT|LIST|PROBE] -f filepath -a args\r\n",
progname);
getchar();
}
int main(int argc, char *argv[])
{
char ch, filepath[256], cmd[256];
char **child_argv = NULL;
int child_argc = 0, i;
ACL_ARGV *argv_tmp;
filepath[0] = 0;
cmd[0] = 0;
init();
while ((ch = getopt(argc, argv, "d:f:a:h")) > 0) {
switch(ch) {
case ''d'':
ACL_SAFE_STRNCPY(cmd, optarg, sizeof(cmd));
break;
case ''f'':
ACL_SAFE_STRNCPY(filepath, optarg, sizeof(filepath));
break;
case ''a'':
argv_tmp = acl_argv_split(optarg, "|");
assert(argv_tmp);
child_argc = argv_tmp->argc;
child_argv = (char**) acl_mycalloc(child_argc + 1, sizeof(char*));
for (i = 0; i < child_argc; i++) {
child_argv[i] = acl_mystrdup(argv_tmp->argv[i]);
}
child_argv[i] = NULL;
acl_argv_free(argv_tmp);
break;
case ''h'':
usage(argv[0]);
return (0);
default:
usage(argv[0]);
return (0);
}
}
if (strcasecmp(cmd, "STOP") == 0) {
// 向守护进程发送消息命令,停止某个子进程或所有的子进程
if (filepath[0])
acl_proctl_stop_one(argv[0], filepath, child_argc, child_argv);
else
acl_proctl_stop_all(argv[0]);
} else if (strcasecmp(cmd, "START") == 0) {
if (filepath[0] == 0) {
usage(argv[0]);
return (0);
}
// 向守护进程发送消息命令,启动某个子进程
acl_proctl_start_one(argv[0], filepath, child_argc, child_argv);
} else if (strcasecmp(cmd, "QUIT") == 0) {
// 向守护进程发送消息命令,停止所有的子进程同时守护父进程也退出
acl_proctl_quit(argv[0]);
} else if (strcasecmp(cmd, "LIST") == 0) {
// 向守护进程发送消息命令,列出由守护进程管理的正在运行的所有子进程
acl_proctl_list(argv[0]);
} else if (strcasecmp(cmd, "PROBE") == 0) {
if (filepath[0] == 0) {
usage(argv[0]);
return (0);
}
// 向守护进程发送消息命令,探测某个子进程是否在运行
acl_proctl_probe(argv[0], filepath);
} else {
// 父进程以守护进程方式启动
char buf[MAX_PATH], logfile[MAX_PATH], *ptr;
// 获得父进程执行程序所在的磁盘路径
acl_proctl_daemon_path(buf, sizeof(buf));
ptr = strrchr(argv[0], ''\\'');
if (ptr == NULL)
ptr = strrchr(argv[0], ''/'');
if (ptr == NULL)
ptr = argv[0];
else
ptr++;
snprintf(logfile, sizeof(logfile), "%s/%s.log", buf, ptr);
// 打开日志文件
acl_msg_open(logfile, "daemon");
// 打开调试信息
acl_debug_init("all:2");
// 以服务器模式启动监控进程
acl_proctl_deamon_init(argv[0]);
// 父进程作为守护进程启动
acl_proctl_daemon_loop();
}
if (child_argv) {
for (i = 0; child_argv[i] != NULL; i++) {
acl_myfree(child_argv[i]);
}
acl_myfree(child_argv);
}
return (0);
}
2.2、子进程
acl_project\samples\proctl\proctlc.cpp
// proctlc.cpp : 定义控制台应用程序的入口点。
//
#pragma comment(lib,"ws2_32")
#include "lib_acl.h"
static void onexit_fn(void *arg acl_unused)
{
printf("child exit now\r\n");
}
int main(int argc, char *argv[])
{
int i;
acl_socket_init();
acl_msg_open("debug.txt", "proctlc");
acl_msg_info(">>> in child progname(%s), argc=%d\r\n", argv[0], argc);
if (argc > 1)
acl_msg_info(">>> in child progname, argv[1]=(%s)\r\n", argv[1]);
// 子进程启动,同时注册自身信息
acl_proctl_child(argv[0], onexit_fn, NULL);
for (i = 0; i < argc; i++) {
acl_msg_info(">>>argv[%d]:%s\r\n", i, argv[i]);
}
i = 0;
while (1) {
acl_msg_info("i = %d\r\n", i++);
if (i == 5)
break;
else
sleep(1);
}
return (-1); // 返回 -1 是为了让父进程继续启动
}
2.3、编译、运行
可以打开 acl_project\win32_build\vc\samples\samples_vc2003.sln,编译其中的 proctlc, proctld 两个工程,便会生成两个可执行文件:proctlc.exe(子进程程序),proctld.exe(父进程程序)。
先让父进程以守护进程模式启动 proctld.exe,然后运行 proctld.exe -d START {path}/proctlc.exe 通知父进程启动子进程;可以运行 proctld.exe -d LIST 列出当前正在运行的子进程,运行 proctld.exe -d PROBE {path}/proctld.exe 判断子进程是否在运行,运行 proctld.exe -d STOP {path}/proctld.exe 让守护父进程停止子进程,运行 proctld.exe -d QUID 使守护进程停止所有子进程并自动退出。
另外,从子进程的程序可以看出,每隔5秒子进程就会异常退出,则守护进程便会立即重启该子进程,如果子进程死的过于频繁,则守护进程会延迟重启子进程,以防止太过耗费系统资源。
三、小结
因为有守护进程保护,就不必担心子进程(即你的工作进程)异常崩溃了,这种父子进程模型可以应用于大多数工作子进程偶尔异常崩溃的情形,如果你的程序 BUG太多,每一会儿就崩溃好多次,建议你还是先把主要问题解决后再使用父子进程,毕竟如果你的程序太过脆弱,虽然父进程能不断地重启你的程序,但你还是不能为用户提供正常服务。这种模型适用于在WIN32平台下,你的程序可能写得比较复杂,程序基本上是比较健壮的,只是会因偶尔某些原因而异常退出的情况。
关于ACL库的在线帮助可以参照:http://acl.sourceforge.net/
activemq所在的java进程如果启动子进程,该父进程重启后与之前的connection都失连,经定位,发现父进程关闭后,子进程中发生阻塞
activemq所在的java进程如果启动子进程,该父进程重启后与之前的connection都失连,经定位,发现父进程关闭后,子进程中发生阻塞:
"ActiveMQ Transport: tcp:///127.0.0.1:61616@10773" prio=6 tid=0x000000000a9ef000 nid=0x3310 runnable [0x000000000f47f000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at org.apache.activemq.transport.tcp.TcpBufferedInputStream.fill(TcpBufferedInputStream.java:50)
at org.apache.activemq.transport.tcp.TcpTransport$2.fill(TcpTransport.java:604)
at org.apache.activemq.transport.tcp.TcpBufferedInputStream.read(TcpBufferedInputStream.java:58)
at org.apache.activemq.transport.tcp.TcpTransport$2.read(TcpTransport.java:589)
at java.io.DataInputStream.readInt(DataInputStream.java:370)
at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:275)
at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:221)
at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:213)
at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:196)
at java.lang.Thread.run(Thread.java:662)
Locked ownable synchronizers:
- None
linux fork 父子进程共享指针
int main (void) { int *p = malloc(sizeof(int)); *p = 0; printf("start main()\n"); int pid = fork(); if (pid == 0) { printf("i am child, my pid is %d\n", getpid()); printf("%d\n", p); *p += 5; } else { printf("i am parent, my pid is %d\n", getpid()); printf("%d\n", p); *p += 2; } printf("%d\n", *p); return 0; }
本意是初始化一个在父子进程共享的指针,期望*p的最后结果是7,奇怪的是指针位置没有改变,但是两个进程的操作并没有产生叠加,请问为什么?
linux – 使用SIGKILL杀死父进程和子进程
我正在编写一个shell脚本,其中我有父进程,并且它具有由sleep& amp;创建的子进程.命令.现在我想杀死父进程,以便子进程也将被杀死.我能用以下命令做到这一点:
trap "kill $$" SIGINT
trap 'kill -HUP 0' EXIT
trap 'kill $(jobs -p)' EXIT
这些命令正在使用kill [parent_process_ID]命令,但如果我使用kill -9 [parent_process_ID],那么只会杀死父进程.
请进一步指导我实现此功能,以便当我使用任何命令终止父进程时,也应该杀死子进程.
如果希望给定组的所有进程都接收信号,则必须将信号发送到进程组.
kill -9 -parentpid
否则,孤儿将被链接到init.
通过在prctl()系统调用中指定选项PR_SET_PDEATHSIG,子代可以要求内核在父级死亡时传递SIGHUP(或其他信号),如下所示:
prctl(PR_SET_PDEATHSIG,SIGHUP);
有关详细信息,请参阅man 2 prctl.
关于如何与子进程共享父进程的numpy随机状态?和子进程和父进程不共享地址空间的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于ACL编程之父子进程机制,父进程守护子进程以防止子进程异常退出、activemq所在的java进程如果启动子进程,该父进程重启后与之前的connection都失连,经定位,发现父进程关闭后,子进程中发生阻塞、linux fork 父子进程共享指针、linux – 使用SIGKILL杀死父进程和子进程的相关信息,请在本站寻找。
本文标签: