как использовать потоки и массив в C - PullRequest
1 голос
/ 16 марта 2011

вопрос в следующем: написать программу с глобальным целочисленным одномерным массивом A размера N с коэффициентом M. с использованием потоков, основной поток инициализирует A и M случайными целыми числами, создает N потоков так, что i-й поток находит Ai =M * Ai, и, наконец, печатает массив A.

моя проблема: у меня ошибка с инициализацией массива, и я не уверен в правильности создания потоков.Надеюсь, я четко объяснил свою проблему.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int M;
int [10] A;

void *run(void *t)
{
   A[(int)t]=A[(int)t]*M;
   pthread_exit(NULL);
}


int main()
{
   pthread_t [10] th;
   srand(time(0))%20;
   M=rand();
   int t;
   for(t = 0; t < 10; t++)
   {
     pthread_create(&th[t], NULL, run, (void *)t);
   }

   int j;
   for(j=0;j<10;j++)
    A[j]=j;

   int i;
   for(i = 0; i < 10; i++)
   {
     pthread_join(th[i], NULL);
     printf("%d:  %d\n", i,A[i]);
   }

   printf("Thread main\n");
   pthread_exit(NULL);
}

это ошибки:

que1.c:5: error: expected identifier or ‘(’ before ‘[’ token
que1.c: In function ‘run’:
que1.c:9: error: ‘A’ undeclared (first use in this function)
que1.c:9: error: (Each undeclared identifier is reported only once
que1.c:9: error: for each function it appears in.)
que1.c: In function ‘main’:
que1.c:16: error: expected identifier or ‘(’ before ‘[’ token
que1.c:17: error: void value not ignored as it ought to be
que1.c:22: error: ‘th’ undeclared (first use in this function)
que1.c:27: error: ‘A’ undeclared (first use in this function)

Ответы [ 3 ]

4 голосов
/ 16 марта 2011

Похоже, у вас есть фон Java (или D), как вы написали int [10] A. Вы можете прочитать это как A - переменная в массиве типа 10 ints . Но в Си эти вещи немного отличаются. В C есть только отдельные примитивные переменные, и они могут быть расположены в наборах непрерывной памяти, которая затем называется массивом. Вот почему был выбран синтаксис int A[10];, что означает: A - указатель на целое число, указывающий начало автоматически выделенного хранилища для 10 целых чисел .

Следующая проблема с вашей программой, хотя компилятор не будет сообщать, что она передает целое число через тип void*. В C каждый указатель может быть преобразован в некоторое целое число, но не все целочисленные значения делают указатели. Указатели в C являются абстрактными вещами: большинство реализаций предпочитают использовать адрес памяти в качестве целочисленного представления. Но было бы так же правильно отобразить их через инъективную LUT. Таким образом, некоторые целочисленные значения могут не отображаться на указатель и поэтому не могут быть правильно переданы. Вы должны действительно передать реальный указатель.

Кроме того, использование вами тем неоптимально. В вашем случае вы уничтожаете строки кеша, как сумасшедшие, и издержки на переключение съедят любой выигрыш при распараллеливании. Как правило, вы должны создавать не более «количество ядер ЦП» + 2 потоков. Учитывая все это, вы можете сделать следующее:

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

/* some prime number, so show what happens with uneven work sizes */
#define ELEMENTS 17

int M;
int A[ELEMENTS];

struct WorkletInfo {
   int *data_base;
   int count;
};

void *worklet(void *t)
{
   int i;
   struct WorkletInfo *wi = t; /* note: no cast here */
   if(!wi)
       return 0;

   for(i=0; i < wi->count; i++)
       wi->data_base[i] *= M;

   return wi;
}

#define N_CPUS 4
#define NUM_THREADS (N_CPUS+1)

int main(int argc, char *argv[])
{
   int t, ec;
   pthread_t th[NUM_THREADS];
   int remaining_elements;
   int const elements_per_worklet = ELEMENTS/NUM_THREADS;

   srand(time(0));
   M=rand();

   /* you must initialize the data a thread will access before starting the thread */
   for(t = 0; t < ELEMENTS; t++)
       A[t]=t+1; /* 0 * x = 0, so give it some nonzero value */

   remaining_elements = ELEMENTS - (elements_per_worklet*NUM_THREADS);
   ec = 0;
   for(t = 0; t < NUM_THREADS; t++)
   {
       struct WorkletInfo *wi = malloc(sizeof(*wi));
       wi->data_base = &A[ec];

       wi->count = elements_per_worklet;
       if(t<remaining_elements) {
           wi->count++;
       }
       ec += wi->count;

       pthread_create(&th[t], NULL, worklet, wi);
   }

   ec = 0;
   for(t = 0; t < NUM_THREADS; t++)
   {
       int i;
       struct WorkletInfo *wi;
       void *retval;
       pthread_join(th[t], &retval);

       if(!retval)
           continue;

       wi = retval;

       for(i = 0; i < wi->count; i++, ec++)
           printf("worklet %d, worklet element %d => total element %d:  %d\n", 
              t, i, ec, 
          wi->data_base[i]);

       free(wi);
       }

   printf("Thread main\n");

   return 0;
}

Вывод этой программы выглядит следующим образом:

worklet 0, worklet element 0 => total element 0:  300787748
worklet 0, worklet element 1 => total element 1:  601575496
worklet 0, worklet element 2 => total element 2:  902363244
worklet 1, worklet element 0 => total element 3:  1203150992
worklet 1, worklet element 1 => total element 4:  1503938740
worklet 1, worklet element 2 => total element 5:  1804726488
worklet 1, worklet element 3 => total element 6:  2105514236
worklet 2, worklet element 0 => total element 7:  -1888665312
worklet 2, worklet element 1 => total element 8:  -1587877564
worklet 2, worklet element 2 => total element 9:  -1287089816
worklet 3, worklet element 0 => total element 10:  -986302068
worklet 3, worklet element 1 => total element 11:  -685514320
worklet 3, worklet element 2 => total element 12:  -384726572
worklet 3, worklet element 3 => total element 13:  -83938824
worklet 4, worklet element 0 => total element 14:  216848924
worklet 4, worklet element 1 => total element 15:  517636672
worklet 4, worklet element 2 => total element 16:  818424420
Thread main exit
2 голосов
/ 16 марта 2011

Помимо ответа @Oli Charlesworth, srand не возвращает никаких значений, он объявлен как void, поэтому вы не можете написать srand(time(0)) % 20.

2 голосов
/ 16 марта 2011

Ваша первая проблема - чисто синтаксическая. Это недействительно C:

int [10] A;

Должно быть:

int A[10];

Аналогично для pthread_t [10] th;.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...