如何在 SimGrid 中同时正确设置属性?
How to properly set properties simultaneously in SimGrid?
有一个进程启动了 100 个进程:
for (int i = 0; i < 100; ++i) {
MSG_process_create("w", executor, NULL, MSG_host_self());
}
执行者创建示例任务并执行它。所以有 100 个进程同时开始执行任务并同时完成任务。为了监控进程数,我有 void plusOneActiveProcess()
和 void minusOneActiveProcess()
:
因为所有 executor
个进程同时启动,所以一切正常:
[ 0.000000] (2:w@Worker) Active process amount is 1
[ 0.000000] (3:w@Worker) Active process amount is 2
[ 0.000000] (4:w@Worker) Active process amount is 3
....................................................
[ 0.000000] (101:w@Worker) Active process amount is 100
当 executor
完成任务执行时,每个进程都应该(如我所料)逐步减少活动进程的数量。但这并没有发生:
[100.000000] (101:w@Worker) Active process amount is 99
[100.000000] (2:w@Worker) Active process amount is 99
[100.000000] (3:w@Worker) Active process amount is 99
....................................................
[100.000000] (100:w@Worker) Active process amount is 99
如何正确操作?
这是函数的代码 plusOneActiveProcess()
, minusOneActiveProcess
, executor()
:
int executor(){
plusOneActiveProcess();
msg_error_t a = MSG_task_execute(MSG_task_create("", 1e9, 0, NULL));
minusOneActiveProcess();
MSG_process_kill(MSG_process_self());
return 0;
}
void plusOneActiveProcess(){
char kot[50];
long number;
number = xbt_str_parse_int(MSG_host_get_property_value(MSG_host_self(), "activeProcess"), "error");
number++;
sprintf(kot, "%ld", number);
MSG_host_set_property_value(MSG_host_self(), "activeProcess", xbt_strdup(kot), NULL);
XBT_INFO("Active process amount is %s", MSG_host_get_property_value(MSG_host_self(), "activeProcess"));
memset(kot, 0, 50);
}
void minusOneActiveProcess(){
char kot[50];
long number;
number = xbt_str_parse_int(MSG_host_get_property_value(MSG_host_self(), "activeProcess"), "error");
number--;
sprintf(kot, "%ld", number);
MSG_host_set_property_value(MSG_host_self(), "activeProcess", xbt_strdup(kot), NULL);
//XBT_INFO("Active process amount is %s", MSG_host_get_property_value(MSG_host_self(), "activeProcess"));
memset(kot, 0, 50);
}
啊哈,这很有趣。问题是 set_property() 是一个 SimGrid simcall,因此您可以保证对 set_property() 的所有调用将始终以相同的顺序线性化。但是 get_property() 是一个常规函数调用,它 returns 调度轮开始时的值。由于所有进程都在同一轮调度中询问该值,因此它们都获得相同的值(即 100),将其递减,然后执行 simcall 以推送新值(所有进程都希望推送 99)。
您想使 get+set 成为原子操作,即确保任何进程在其他人执行 get_property() 之前推送更新的值。为此,我建议使用 SimGrid Mutexes 或其他东西。
有一个进程启动了 100 个进程:
for (int i = 0; i < 100; ++i) {
MSG_process_create("w", executor, NULL, MSG_host_self());
}
执行者创建示例任务并执行它。所以有 100 个进程同时开始执行任务并同时完成任务。为了监控进程数,我有 void plusOneActiveProcess()
和 void minusOneActiveProcess()
:
因为所有 executor
个进程同时启动,所以一切正常:
[ 0.000000] (2:w@Worker) Active process amount is 1
[ 0.000000] (3:w@Worker) Active process amount is 2
[ 0.000000] (4:w@Worker) Active process amount is 3
....................................................
[ 0.000000] (101:w@Worker) Active process amount is 100
当 executor
完成任务执行时,每个进程都应该(如我所料)逐步减少活动进程的数量。但这并没有发生:
[100.000000] (101:w@Worker) Active process amount is 99
[100.000000] (2:w@Worker) Active process amount is 99
[100.000000] (3:w@Worker) Active process amount is 99
....................................................
[100.000000] (100:w@Worker) Active process amount is 99
如何正确操作?
这是函数的代码 plusOneActiveProcess()
, minusOneActiveProcess
, executor()
:
int executor(){
plusOneActiveProcess();
msg_error_t a = MSG_task_execute(MSG_task_create("", 1e9, 0, NULL));
minusOneActiveProcess();
MSG_process_kill(MSG_process_self());
return 0;
}
void plusOneActiveProcess(){
char kot[50];
long number;
number = xbt_str_parse_int(MSG_host_get_property_value(MSG_host_self(), "activeProcess"), "error");
number++;
sprintf(kot, "%ld", number);
MSG_host_set_property_value(MSG_host_self(), "activeProcess", xbt_strdup(kot), NULL);
XBT_INFO("Active process amount is %s", MSG_host_get_property_value(MSG_host_self(), "activeProcess"));
memset(kot, 0, 50);
}
void minusOneActiveProcess(){
char kot[50];
long number;
number = xbt_str_parse_int(MSG_host_get_property_value(MSG_host_self(), "activeProcess"), "error");
number--;
sprintf(kot, "%ld", number);
MSG_host_set_property_value(MSG_host_self(), "activeProcess", xbt_strdup(kot), NULL);
//XBT_INFO("Active process amount is %s", MSG_host_get_property_value(MSG_host_self(), "activeProcess"));
memset(kot, 0, 50);
}
啊哈,这很有趣。问题是 set_property() 是一个 SimGrid simcall,因此您可以保证对 set_property() 的所有调用将始终以相同的顺序线性化。但是 get_property() 是一个常规函数调用,它 returns 调度轮开始时的值。由于所有进程都在同一轮调度中询问该值,因此它们都获得相同的值(即 100),将其递减,然后执行 simcall 以推送新值(所有进程都希望推送 99)。
您想使 get+set 成为原子操作,即确保任何进程在其他人执行 get_property() 之前推送更新的值。为此,我建议使用 SimGrid Mutexes 或其他东西。