0

スレッドに関する緊急の支援が必要です: ここでの目標は、separtemask が各画像を取得し、異なる輪郭を分離し、画像の輪郭ごとに handleobject スレッドを呼び出すことです。したがって、すべての for ループは handeobject スレッドを呼び出します。ただし、オブジェクト インデックス変数は各スレッドで渡す必要があります。ただし、objectndex の最後の値のみが渡されます。これは、speratemask 関数がループして obj.objindx の値を置き換え、obj.objindx の最後の値のみがすべてのスレッドに渡されるためです。とにかく、handleobject に各 objectindex 値を渡す方法はありますか。pthread_join(tid[objectIndex],NULL); のコメントを外すと、コードは正常に実行されます。しかし、それは並列プログラムを提供しません

void separateMask(IplImage *maskImg)
{    
  for(r = contours; r != NULL; r = r->h_next)
  {
    cvSet(objectMaskImg, cvScalarAll(0), NULL);
    CvScalar externalColor = cvScalarAll(0xff);
    CvScalar holeColor = cvScalarAll(0x00);
    int maxLevel = -1; 
    int thinkness = CV_FILLED; 
    int lineType = 8; /* 8-connected */
    cvDrawContours(objectMaskImg, r, externalColor, holeColor, maxLevel, thinkness,lineType, cvPoint(0,0));;
    obj.objectMaskImg1[objectIndex]=(IplImage *) malloc(sizeof(IplImage));
    obj.objectMaskImg1[objectIndex]=objectMaskImg;
    obj.objindx=objectIndex;
    obj.intensityOut1=intensityOut;
    obj.tasOut1=tasOut;
    pthread_create(&tid[objectIndex],NULL,handleObject,(void *)&obj);
    //pthread_join(tid[objectIndex],NULL);
    printf("objectindx %d\n",obj.objindx);
    objectIndex++;

  }
  // cvReleaseImage(&objectMaskImg);
  //cvReleaseMemStorage(&storage);
  printf("Exitng Separatemask\n");

}


void* handleObject(void *arg)
{
  int i, j;
  handle *hndl;
  hndl=(handle *) malloc(sizeof(handle));
  hndl=(handle*)arg;
  pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
  pthread_mutex_lock(&lock);
  IplImage *pImg;
  float statistics_ratio[3][9];
  pthread_t tid3;
  tas3 tas2;
  pImg = cvLoadImage("image.tif", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
  if(pImg == NULL)
  {
    fprintf(stderr, "Fail to load image %s\n", "tiff file");
    return ;
  }
  tas2.pImg1=pImg;
  printf("tst%d\n",hndl->objindx);
  tas2.x=hndl->objindx;
  tas2.objectMaskImg1=hndl->objectMaskImg1[tas2.x];
  tas2.statistics_ratio[3][9]=statistics_ratio[3][9];
  double mean = average_intensity(pImg, tas2.objectMaskImg1); 
  int total = total_white(pImg, tas2.objectMaskImg1);
  pthread_mutex_unlock(&lock);

  printf("Exiting handle object thread_id %d\n\n", pthread_self());
}
4

2 に答える 2

2

この機能には問題があるようです

void* handleObject(void *arg)

まずは

    pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_lock(&lock);

これはローカルに作成されたミューテックスですが、スレッド関数内で作成されました。それであなたはそれをロックしますが、他にはミューテックスを見ることができないので、なぜそれが必要なのですか??? 他のスレッドが参照できない場合、同期機能は提供されません。第二に

    float statistics_ratio[3][9];
    pthread_t tid3;
    tas3 tas2;
    pImg = cvLoadImage("image.tif", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
    if(pImg == NULL){
        fprintf(stderr, "Fail to load image %s\n", "tiff file");
        return ;
    }
    tas2.pImg1=pImg;
    printf("tst%d\n",hndl->objindx);
    tas2.x=hndl->objindx;
    tas2.objectMaskImg1=hndl->objectMaskImg1[tas2.x];
    tas2.statistics_ratio[3][9]=statistics_ratio[3][9];

ローカルの初期化されていない 2D float 配列を作成し、statistics_ratio何もせずにローカルに作成された別のオブジェクト メンバーに割り当てます。別の pthread インスタンスの宣言と同様に、これは無意味に見えますtid3

他にはスレッドを見ることができないため、実際には問題ではありませんが、pImg == NULL最初にミューテックスのロックを解除しない場合は、この関数内から戻ります。

なぜあなたのコードが動かないのか、何をしようとしているのかを理解するのは非常に難しいですが、上で強調したことが役立つかもしれません。使用されていないスレッド関数内に多くのローカル変数を作成しています。これらのいくつかを代わりにグローバルにする必要があるかどうかはわかりません-特にミューテックス(実際に必要な場合)。

于 2012-07-12T20:27:04.137 に答える
1

最初の問題はobj、作成したスレッドに渡す構造を再利用しているため、作成したスレッドが別のスレッド向けのデータで上書きされた情報を読み取るデータ競合が発生することだと思います。

スレッドを作成するループの構造は次のとおりです。

for(r = contours; r != NULL; r = r->h_next)
{
    // initialize obj with information for the thread
    // ...

    // create a thread and pass it a pointer to obj
    pthread_create(&tid[objectIndex],NULL,handleObject,(void *)&obj);

    // some other bookkeeping
}

次のループ反復ですぐに obj を再初期化するので、スレッド関数が取得するデータを誰が知っていますか? そのため、スレッドを作成した後にスレッドに参加するとobj、スレッドが終了するまでループがブロックされるため、構造は安定したままになります。

ループを次のように変更します。

for(r = contours; r != NULL; r = r->h_next)
{
    // instead of using `obj`, allocate a struct using malloc
    handle* threaddata = malloc(sizeof(handle); // note: I'm not sure if `handle` is the right type

    // initialize *threaddata with information for the thread
    // ...

    // create a thread and pass it the threaddata pointer
    pthread_create(&tid[objectIndex],NULL,handleObject,threaddata);

    // some other bookkeeping
}

次にfree()、終了後のスレッド関数内のデータ (つまり、スレッド作成コードがデータのブロックを作成して初期化し、その所有権をスレッドに渡します)。

objこれは、構造体にスレッドごとの情報が既に含まれているように見えるため、通常ほど単純ではない可能性があることに注意してください(objectMaskImg1要素は、各要素が個別のスレッドを対象としている配列のように見えます)。そのため、データ構造のリファクタリングも必要になる場合があります。

最後に、malloc() によって割り当てられたブロックへのポインターを即座に上書きするなど、他にもいくつかの明らかなバグがあります。

obj.objectMaskImg1[objectIndex]=(IplImage *) malloc(sizeof(IplImage));
obj.objectMaskImg1[objectIndex]=objectMaskImg;

hndl=(handle *) malloc(sizeof(handle));
hndl=(handle*)arg;

handleObject()mathematician1975 (http://stackoverflow.com/a/11460092/12711) によって言及されているスレッド関数でのミューテックスの無意味な使用に加えて。

スレッド関数のかなりの部分のコード (データをローカルにコピーまたはコピーしようとするミューテックス) は、問題の内容を実際に理解せずに問題を修正しようとするために投入されたもののようです。さまざまなデータが存在する場所、データをコピーする方法 (データへのポインターを単にコピーするのではなく)、およびデータの所有権を管理する方法を理解する必要があると思います。

于 2012-07-14T19:23:32.193 に答える