使用 pthread 分割和搜索数组段的问题

Posted

技术标签:

【中文标题】使用 pthread 分割和搜索数组段的问题【英文标题】:Problems splitting and searching array segments with pthreads 【发布时间】:2017-05-15 23:06:06 【问题描述】:

我正在做一个个人项目,用随机数填充数组,使用 pthread (POSIX) 拆分为多个用户定义的段,在每个段中搜索目标,并返回目标的次数成立。我有错误和问题。对于多个线程,诸如目标未保存在结构成员中和未创建线程等问题会发生。我确定我的逻辑是关闭的,我的代码和它的输出反映了这一点,但我很难过。如何将数组拆分为线程?我在搞砸什么逻辑?

头文件...

#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


【问题讨论】:

你没有pthread_createpthread_join的头文件 【参考方案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;

并在此printf 中将infoPtr 的第二次使用更进一步:

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

事情会变得更好。

在您的firstlast 设置中还有更多的错误挥之不去。我建议您打印出它们的值,并确保它们以您想要的方式出现。我能够很容易地让它们变得消极(并开始搜索随机记忆)。

【讨论】:

我现在明白了。我能够解决第一个和最后一个问题,但是 pthread 存在问题。 for 循环将启动,打印出第一个和最后一个(这样我每次都能看到里面的内容),然后不创建线程。它只是跳过 pthread_create 并回到顶部。我不知道为什么会发生这种情况。我应该尝试在 for 循环的底部还是顶部添加分配内容? 其实我想通了。我没有增加我的索引等。感谢您的帮助!

以上是关于使用 pthread 分割和搜索数组段的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何为 3 个不同的事件(信号量、pthread 条件和阻塞套接字接收)阻塞单个线程?

Pthread_create 在 C++ 中导致分段错误

python 通过.pth文件修改搜索路径

C++如何将一个字符数组分割成几个数组?

一旦std:thread进入C ++ Ox,pthreads是不是会过时[关闭]

在 C 中使用 pthread 的数组的最小值和最大值