【发布时间】:2020-11-16 22:38:30
【问题描述】:
我正在尝试生成介于 -1 和 +1 之间的随机浮点数,总数由用户指定以及线程数,然后随机数的总数在线程之间平均分配,线程都使用一个工作区结构。
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
typedef struct WorkspaceStruct {
unsigned int tid;
int points_generated;
int points_in_circle;
unsigned int seed;
}Workspace;
void *worker(void *ws) {
Workspace *workspace = (Workspace *) ws; // link worker to workspace
pthread_mutex_lock(&mutex);
printf("Worker %d\n", workspace->tid);
int max = workspace->points_generated;
unsigned int seed = workspace->seed;
for (int i = 0; i < max; ++i) {
float point_x = (float)rand_r(&seed) / RAND_MAX * 2.0 - 1.0;
float point_y = (float)rand_r(&seed) / RAND_MAX * 2.0 - 1.0;
printf("x: %f, y: %f\n", point_x, point_y);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void calculate_circle_area(int total_samples, int no_workers) {
pthread_t worker_thread[no_workers];
Workspace workspace;
workspace.points_generated = total_samples / no_workers;
workspace.tid = 0;
workspace.seed = time(0);
for (int i = 0; i < no_workers; ++i) {
workspace.tid += 1;
pthread_create(&worker_thread[i], NULL, worker, &workspace);
pthread_join(worker_thread[i], NULL);
}
}
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("usage: ./program [no. of samples] [no. of worker threads]\n");
return EXIT_FAILURE;
} else {
int total_samples = atoi(argv[1]);
int no_workers = atoi(argv[2]);
printf("\n");
calculate_circle_area(total_samples, no_workers);
printf("\n");
return EXIT_SUCCESS;
}
}
这非常有效,它确实生成了随机数并且所有内容都被正确拆分,但是每个线程生成相同的数字,但是线程中的每个数字都不同。
命令示例输出:./calc_area 9 3(总共生成 9 个随机数,使用 3 个线程)
Worker 1
x: 0.506291, y: -0.765927
x: -0.941786, y: -0.598265
x: 0.962658, y: -0.609824
Worker 2
x: 0.506291, y: -0.765927
x: -0.941786, y: -0.598265
x: 0.962658, y: -0.609824
Worker 3
x: 0.506291, y: -0.765927
x: -0.941786, y: -0.598265
x: 0.962658, y: -0.609824
我希望每个线程彼此生成不同的数字,我该怎么做?谢谢
【问题讨论】:
-
你认为“种子”应该做什么?此外,如果您在持有互斥锁的同时运行整个工作,则单线程将比多线程快得多。
-
man rand_r:如果调用 rand_r() 时使用与 seedp 指向的整数相同的初始值,并且在调用之间不修改该值,则将产生相同的伪随机序列。
-
您应该将
workspace->seed直接传递给每个rand_r调用,而不是使用本地副本。这样共享种子可以被每个线程更新和使用。 -
OT:拥有多个线程并围绕整个事物进行大锁是毫无意义的,这实际上是对每个线程进行序列化。这可能是因为这是一项学术练习,但您可能想检查您是否完全满足了最初的要求。
标签: c multithreading random pthreads