使用pthreads分割和搜索数组段时出现问题

时间:2017-05-15 23:06:07

标签: c arrays multithreading

我正在开发一个个人项目,用随机数填充数组,使用pthread(POSIX)拆分为多个用户定义的段,在每个段中搜索目标,并返回目标的次数找到。我有错误和问题。对于多个线程,问题包括目标没有保存在struct成员中,而是一个未创建的线程和其他事情发生。我确定我的逻辑是关闭的,我的代码和它的输出反映了这一点,但我很难过。你如何将数组拆分成线程?我弄乱了什么逻辑?

HEADER FILE ...

#ifndef COUNT_ARRAY_H
#define COUNT_ARRAY_H


// structure declarations
typedef struct
{
 int     threadNum;
 int     *array;
 int     first;
 int     last;
 int     target;
 int     numFound;

} ThreadInfo;


// function prototypes
void*   ThreadFunc(void  *vptr);


#endif  // COUNT_ARRAY_H

主要文件....

 #include    <pthread.h>
 #include    <stdio.h>
 #include    <stdlib.h>
 #include    "count_array.h"

 int     main(void)
 {
  int                 numSegs;
  int                 numSegElems;
  int                 maxRand;
  int                 target;
  int                 totalElems;
  int                 totalFound = 0;
  ThreadInfo          *infoPtr;
  pthread_t           *threadHandles;
  int                 index = 0;
  int                 first;
  int                 last;
  int                 threadNum = 0;

//get primary info from user...
printf(" Please enter the total number of elements? ");
scanf("%d", &totalElems);

printf(" Please enter the maximum random value: ");
scanf("%d", &maxRand);

printf(" Please enter the number of segments (1 to 15857): ");
scanf("%d", &numSegs);

 if(numSegs > 15857)
   {
    puts(" Too many segments for machine!");
    exit(EXIT_FAILURE);
   }

 numSegElems = totalElems/numSegs;

// configure the array to work with
// declare array here...

 int myArray[totalElems];

//and fill array here
for(; index < totalElems; index++)
   {
    // % rand() and maxRand to get good range and
    //not go beyond users max number
    myArray[index] = (rand() % maxRand);

    //test printf...ignore if still here
    printf(" %d \n", myArray[index]);
   }

// get the target value to look for
 printf(" Please enter the target value: ");
 scanf("%d",&target);

// display initial information
printf("*** Begin search: target = %d, # elements = %d, # segments = %d, "
                                            "# segment elements = %d\n"
                                                            , target
                                                            , totalElems
                                                            , numSegs
                                                            , numSegElems);

// initialize the array first/last indexes into the integer array
  if(numSegs == 1)
    {
     first = totalElems;
     last = 0;
    }
  else
    {
     first = totalElems - numSegElems;
     last = (first - numSegElems);
    }
// allocate an array to store the thread handles

   int size; //size of segment
   if(numSegs > 1)
     {

      size = numSegElems;
     }
   else
     {
      size = totalElems;
     }

    //test printf...please ignore if still here
    //printf(" size %d \n", size);

     int segA[size];//not sure if I need this

// loop and create threads (# of segments)
index = 0;

for(; threadNum < numSegs; index++)
{
    // allocate a thread info structure from the heap
    threadHandles = calloc(totalElems, sizeof(pthread_t));
    infoPtr = calloc(totalElems, sizeof(ThreadInfo));

    // store the information in the allocated structure

      infoPtr[index].threadNum = threadNum;

      infoPtr->target = target;
      infoPtr->first = first;
      infoPtr->last = last;
      infoPtr->array = myArray;


    // create the secondary thread, passing the thread info
      pthread_create(&threadHandles[index], NULL, ThreadFunc, &infoPtr[index]);

    // update the first/last array indexes for the next thread

      first = last;
      last = first-numSegs;
      ++threadNum;
}

// loop and join the threads to fetch each thread's results
  for(index = 0; index < numSegs; index++)
     {
      // join with the next thread
      pthread_join(threadHandles[index], NULL);

      // get the total number of matches from the thread's infoPtr

      // and display a message
      printf(" *** pthread_join returned: threadNum = %d, numFound = %d\n",
                                     infoPtr[index].threadNum, infoPtr->numFound);


     }
        // release the infoPtr structure back to the heap
          free(infoPtr);

// display the final results

// release heap memory
free(threadHandles);

return 0;

}  // end of "main"


void*   ThreadFunc(void  *vptr)
{
 //declare and set vars
 ThreadInfo *ptr = vptr;
 ptr->numFound = 0;
 int index = ptr->first-1;

 //test printf...ignore if still here
  printf(" Targ %d \n", ptr->target);

 //start search
 for(; index >= ptr->last; --index)
    {
      printf(" %d \n", ptr->array[index]);

    //if target found
     if(ptr->target ==  ptr->array[index])
       {
        puts(" Target found! ");
        //increment numFound
        ++ptr->numFound;
       }
    }

     //drop out and display message

}

1 个答案:

答案 0 :(得分:1)

您在threadHandlesinfoPtr的分配中遇到了多个错误。首先,您真的不想分配totalElems个 - 只需要numSegs。其次,更重要的是,每次通过线程调用循环时,您都要重新分配它们并更改指针infoPtrthreadHandles的值。第三,你在这里混合处理infoPtr作为一组ThreadInfo结构:

  infoPtr[index].threadNum = threadNum;

将其视为指向不断变化的ThreadInfo结构的指针:

  infoPtr->target = target;
  infoPtr->first = first;
  infoPtr->last = last;
  infoPtr->array = myArray;

所以每次循环时,你只在第一个线程上设置这些参数。

要解决此问题,请在循环之前编辑并移动分配,并将infoPtr始终视为数组:

threadHandles = calloc(numSegs, sizeof(pthread_t));
infoPtr = calloc(numSegs, sizeof(ThreadInfo));

for(; threadNum < numSegs; index++)
{
  infoPtr[index].threadNum = threadNum;

  infoPtr[index].target = target;
  infoPtr[index].first = first;
  infoPtr[index].last = last;
  infoPtr[index].array = myArray;

并进一步确定infoPtrprintf的第二次使用:

  printf(" *** pthread_join returned: threadNum = %d, numFound = %d\n",
               infoPtr[index].threadNum, infoPtr[index].numFound);

事情会好一点。

firstlast的设置中仍有更多错误。我建议你打印出他们的价值观,并确保他们以你想要的方式出现。我很容易让他们变得消极(并开始搜索随机记忆)。