Похоже, у вас есть фон 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