簡體   English   中英

ANSI C中具有PTHREADS的執行程序池

[英]Executor Pool with PTHREADS in ANSI C

我正在用ANSI C(1972)編寫程序,並且必須使用固定數量的線程。 我基本上讀了一個大文件,其中包含帶有緯度和經度數據的.csv類的記錄,我必須對其進行處理。 問題是我不能在20.00萬行文件上等待2周,並且我需要使用threadsforking

基本上我讀這樣的.txt文件

FILE *file2 = fopen ( lat_long_file, "r" );
if (file2 != NULL)
{
    char line2 [128];

    while (fgets(line2, sizeof line2, file2) != NULL)
    {
        //fputs(line2, stdout);

        char *this_record = trimqq(line2);

        // .....
        // ..... STUFF TO DO (here i must send data to thread function like in JAVA)
        // Thread temp_thread = new Thread(new ThreadClass(arguments ....));
        // temp_thread.start(); <- this is how i would do if i was programming in JAVA
        // .....

    }
}

main_1.c (使用pthread.h線程處理)

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_THREADS     10

static int current_threads = 0;


void *wait(void *t)
{
   int i;
   long tid;

   tid = (long)t;

   // sleep(1);

   system("sleep 3; date;");

   printf("Sleeping in thread\n");
   printf("Thread with id %lu  ...exiting\n",tid);

   pthread_exit(NULL);
}

int main ()
{
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;

   // Initialize and set thread joinable
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( i=0; i < NUM_THREADS; i++ )
   {
     // cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], NULL, wait, (void *)(intptr_t)i );

      if (rc)
      {
        // cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }

    // free attribute and wait for the other threads
    pthread_attr_destroy(&attr);
    for( i=0; i < NUM_THREADS; i++ )
    {
        rc = pthread_join(threads[i], &status);
        if (rc)
        {
            printf("Error:unable to join %d\n",rc);
            exit(-1);
        }

        printf("Main: completed thread id : %d",i);
        printf(" exiting with status : %p\n",status);
    }

    printf("Main: program exiting.\n");

    pthread_exit(NULL);
}

我得到這個ID的輸出

Sleeping in thread
Sleeping in thread
Thread with id 5  ...exiting
Sleeping in thread
Thread with id 0  ...exiting
Sleeping in thread
Sleeping in thread
Sleeping in thread
Thread with id 9  ...exiting
Thread with id 1  ...exiting
Sleeping in thread
Sleeping in thread
Thread with id 7  ...exiting
Thread with id 3  ...exiting
Thread with id 2  ...exiting
Thread with id 6  ...exiting
Sleeping in thread
Thread with id 4  ...exiting
Sleeping in thread
Thread with id 8  ...exiting
Main: completed thread id : 0 exiting with status : (nil)
Main: completed thread id : 1 exiting with status : (nil)
Main: completed thread id : 2 exiting with status : (nil)
Main: completed thread id : 3 exiting with status : (nil)
Main: completed thread id : 4 exiting with status : (nil)
Main: completed thread id : 5 exiting with status : (nil)
Main: completed thread id : 6 exiting with status : (nil)
Main: completed thread id : 7 exiting with status : (nil)
Main: completed thread id : 8 exiting with status : (nil)
Main: completed thread id : 9 exiting with status : (nil)
Main: program exiting.

執行時間為3秒

如果我更改system("sleep 3; date;"); system("sleep 10; date;"); ,執行時間將為10秒,而我希望每次調用void *wait(void *t)函數時都處於休眠狀態...

main_2_fork (我也嘗試過fork,但是沒有用)

#include  <stdio.h>
#include  <string.h>
#include  <sys/types.h>
#include <stdlib.h>

#define   MAX_COUNT  200
#define   BUF_SIZE   100

int random_number(int min_num, int max_num);

void  main(void)
{
    int numforks = 0;
    int maxf = 5;
    int status;

    char   buf[BUF_SIZE];

    pid_t PID; 

    int job = 0;
    for(job; job <= 10; job++)
    {
        // fork() = make a copy of this program from this line to the bottom
        PID = fork();

        int fork_id = random_number(1000000,9999999);

        if (PID < 0) 
        {
            // if -1 then couldn't fork ....
            fprintf(stderr, "[!] Couldn't fork!\n");
            exit(1);
        }
        if (( PID == 0 ))
        {
            // 0 = has created a child process
            exit(0);
        }
        else            
        {
            // means that PID is 1 2 3 .... 30000 44534 534634 .... whatever
            // increment the fork count
            numforks++;

            sprintf(buf, "FORK[#%d] BEGIN pid=%d num_forks=%d\n",fork_id,PID,numforks);
            write(1, buf, strlen(buf));

            // sleep(random_number(1,2));

            char str[300];
            sprintf(str,"sleep %d; ps ax | wc -l",random_number(1,4));
            puts(str);

            // OUTPUT COMMAND BEGIN
            FILE *command_execute = popen(str, "r");
            char buf[256];
            int increment = 0;
            while (fgets(buf, sizeof(buf), command_execute) != 0)
            {
                printf("LINE[%d]:%s",increment,buf);
                increment++;
                break;
            }
            pclose(command_execute);
            // OUTPUT COMMAND END   

            // block to not do extra forks
            if (numforks > maxf)
            {
                for (numforks; numforks > maxf; numforks--)
                {
                    PID = wait(&status);
                }
            }

            sprintf(buf, "FORK[#%d] END pid=%d num_forks=%d\n",fork_id,PID,numforks);
            write(1, buf, strlen(buf));
        }

        // sleep(1);
    }
}

int random_number(int min_num, int max_num)
{
    int result=0,low_num=0,hi_num=0;
    if(min_num<max_num)
    {
        low_num=min_num;
        hi_num=max_num+1; // this is done to include max_num in output.
    }
    else
    {
        low_num=max_num+1;// this is done to include max_num in output.
        hi_num=min_num;
    }
    srand(time(NULL));
    result = (rand()%(hi_num-low_num))+low_num;
    return result;
}

輸出為:

FORK[#7495656] BEGIN pid=29291 num_forks=1
sleep 1; ps ax | wc -l
LINE[0]:312
FORK[#7495656] END pid=29291 num_forks=1
FORK[#9071759] BEGIN pid=29296 num_forks=2
sleep 4; ps ax | wc -l
LINE[0]:319
FORK[#9071759] END pid=29296 num_forks=2
FORK[#2236079] BEGIN pid=29330 num_forks=3
sleep 4; ps ax | wc -l

......

而且執行不是並行的……而是逐個執行,即使我知道fork()函數可以在ps ax | grep 'fork2.exe'創建子進程ps ax | grep 'fork2.exe' ps ax | grep 'fork2.exe' ...

這是我想要的示例: http : //www.javacodegeeks.com/2013/01/java-thread-pool-example-using-executors-and-threadpoolexecutor.html

假設您將5設為一次的最大線程數。

質詢

  1. 為什么void *wait(void *t)函數無法正常睡眠? 為什么pthread是一個接一個地而不是並行地執行它們?
  2. 我應該怎么做才能使線程池的最大線程數固定在C

非常感謝你。

我還不能發表評論,所以我會在這里回復。 您的線程示例僅花費一個線程(您的wait()函數)休眠的時間。 這就是說,如果您這樣寫,將會更加清楚:

void *some_running_task(void *t)
{
   int i;
   long tid = (long)t;

   printf("Sleeping in thread #%lu ...\n", tid);
   system("sleep 3; date;");

   printf("Thread with #%lu ... exiting\n", tid);
   pthread_exit(NULL);
}

正如@fuzxxl所說,標准線程庫中有一個wait(),所以您不應該使用它。

所有線程都在同一時刻啟動,可能只有幾十微秒。 它們都在同一時刻開始,因此都在3秒后結束。 將睡眠指令更改為10秒,程序將持續10秒。

您可能想要的是一個線程池,該線程池在整個工作完成之前一直保持相同數量的線程繁忙: 觸發線程,直到達到要處理的最大池數為止 但是,同步線程池容易產生死鎖。 您也可以讓每個線程處理文件的自己的部分...除非您想要將線程專用於一行。

我在這里看到的與並行性有關的一個問題是序列。 如果您關心序列順序 ,則線程不一定會按照讀取行的順序來產生數據。 因此,除非將處理后的數據與行號一起放入數據庫中,否則將丟失序列順序。

我看到的另一個問題是輸出已處理的數據。 它需要適當的同步,以避免一個線程的輸出不打亂另一個線程的輸出( 當然,假設線程應該打印出它們的數據 )。

對於我來說,除了加速全局處理時間之外,您對並行性的期望還不清楚。 如果您希望一堆線程處理一堆行,無論如何,您都會想出類似且簡單的方法,例如拆分您的源數據文件……當然可以做到。 但是至少您可以在讀取每一行時控制數據的順序,然后就可以退出運行長時間運行的單線程進程,而不是運行長時間運行的多線程應用程序。 單線程應用程序比多線程應用程序更容易編程。

您是否不能強制使用C,例如Python或Cython 最大的優點是為您避免了線程同步的麻煩。

無論如何,有不止一種方法可以加速線性數據處理。 例如,UNIX sed可用於將一定數量的行通過管道傳輸到處理應用程序。 運行多個sed | <processing app> sed | <processing app>根據需要。 或者,您可能只是將數據文件的分割部分通過管道傳送到用C或Python編寫的處理應用程序中。

只是頭條新聞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM