首页 > 解决方案 > 使用线程生成随机数

问题描述

我试图在-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

我希望每个线程彼此生成不同的数字,我该怎么做?谢谢

标签: cmultithreadingrandompthreads

解决方案


由于您包含了多线程标签,因此这是使用 Ada 的解决方案。在这种情况下,随机数种子由每个任务(即线程)重置,确保种子不同,因此随机数序列不同。

with Ada.Text_IO;               use Ada.Text_IO;
with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
with Ada.Float_Text_IO;         use Ada.Float_Text_IO;
with Ada.Integer_Text_IO;       use Ada.Integer_Text_IO;

procedure Main is
   type Point is record
      X : Float;
      Y : Float;
   end record;

   procedure Print (Item : Point) is
   begin
      Put ("X:");
      Put (Item => Item.X, Fore => 2, Aft => 4, Exp => 0);
      Put (" Y:");
      Put (Item => Item.Y, Fore => 2, Aft => 4, Exp => 0);
      New_Line;
   end Print;

   type Point_Array is array (Positive range <>) of Point;

   task type worker is
      entry Set_Num (Count : Positive);
      entry Report;
   end worker;

   task body worker is

      Seed       : Generator;
      Num_Points : Positive;
   begin
      Reset (Seed);
      accept Set_Num (Count : Positive) do
         Num_Points := Count;
      end Set_Num;

      declare
         Buf : Point_Array (1 .. Num_Points);
      begin

         for I in Buf'Range loop
            Buf (I).X := Random (Seed) * 2.0 - 1.0;
            Buf (I).Y := Random (Seed) * 2.0 - 1.0;
         end loop;
         accept Report;
         for I in Buf'Range loop
            Print (Buf (I));
         end loop;
         New_Line;
      end;

   end worker;

   type Team is array (Positive range <>) of worker;
   Num_Tasks : Positive;
   Num_Rand  : Positive;

begin
   Put ("Enter the number of task: ");
   Get (Num_Tasks);
   Put ("Enter the number of results per task: ");
   Get (Num_Rand);
   declare
      Workers : Team (1 .. Num_Tasks);
   begin
      for I in Workers'Range loop
         Workers (I).Set_Num (Num_Rand);
      end loop;
      for I in Workers'range loop
         Put_Line ("Worker" & I'Image);
         Workers (I).Report;
         delay 0.01;
      end loop;
   end;

end Main;

使用 6 个任务和每个任务 4 个结果的执行的输出是:

Enter the number of task: 6
Enter the number of results per task: 4
Worker 1
X: 0.7487 Y:-0.6497
X:-0.9634 Y: 0.6317
X:-0.9189 Y: 0.8070
X: 0.8837 Y:-0.3839

Worker 2
X: 0.6409 Y:-0.4913
X:-0.0185 Y: 0.1078
X:-0.6408 Y:-0.9719
X:-0.6199 Y: 0.9301

Worker 3
X:-0.9440 Y: 0.1089
X:-0.1354 Y:-0.3133
X: 0.8479 Y:-0.7389
X: 0.8399 Y: 0.4826

Worker 4
X:-0.9165 Y:-0.3652
X: 0.4137 Y:-0.6292
X: 0.6467 Y: 0.9344
X: 0.2898 Y: 0.1059

Worker 5
X: 0.8818 Y:-0.3551
X:-0.5161 Y:-0.5251
X:-0.6831 Y:-0.0531
X: 0.8207 Y:-0.7419

Worker 6
X: 0.2529 Y:-0.9385
X: 0.5640 Y: 0.3365
X:-0.4477 Y: 0.1642
X: 0.8230 Y: 0.8284

推荐阅读