2013-02-12 3 views
0

Простой параллельный сумматор. Вы передаете ему указатель на первый элемент в массиве, указатель на последний элемент в массиве, элемент # первого указателя и количество элементов в этой части массива.Некоторые потоки правильно вычисляются, другие не

double my_func (double *x, double *x_last, int first_pos, int n) 
    { 
     if (n ==1) { 
     return x[first_pos]; 
     } 
     else if (n == 2) { 
     return x[first_pos] + x[first_pos+1]; 
     } 
     else { 
     double x1,x2; 

     x1 = _Cilk_spawn my_func (&x[first_pos], &x[n/2+first_pos-1],first_pos, n/2); 
     x2 = my_func (&x[n/2+first_pos],&x[first_pos+n-1],n/2+first_pos, n-n/2); 
     _Cilk_sync; 

     return x1 + x2; 
     } 
    } 

Допустим, мы начинаем с массивом размера 80. Это прекрасно работает для элемента # 0-19 (первый квартал), а затем возвращает связку из 0 '/ мусора для элементов # 20-39 и всех элементов после. Очевидно, что и строки x1 и x2 работают в некоторой степени, но функция ломается, и я не знаю почему. Есть идеи?

ответ

3

Вы нарезка неправильно массив:

x1 = my_func (&x[n/2+first_pos],&x[first_pos+n-1],n/2+first_pos, n-n/2); 
        ^        ^
      new "base" pointer    first pos in slice?! 

Вы не можете пройти как скорректированный указатель на первый элемент Срез в, и глобальный индекс этого элемента. Вы заканчиваете индексирование более одного раза, так сказать, что приводит к разыменованию недействительных адресов.

Для случая n = 80, второй рекурсивный вызов будет проходить x, указывая на элемент &x[80/2+0], т.е. &x[40], но он также будет установлен на first_pos40 для этого вызова. В конечном итоге, вы достигните значения n < 3 и сделайте подсчет используя накопленный first_pos.

Кроме того, входные данные должны быть const, если это доступно только для чтения, для большей ясности.

+0

Я подумал, что мне нужно передать first_pos, чтобы отслеживать, где должны появляться будущие фрагменты. Поэтому, если я хочу добавить x [4: 7], поэтому я пройду (& x [4], & x [7]), но тогда я должен сохранить это 4 для вычисления следующего фрагмента, верно? Думаю, я не понимаю, как это ведет к неверным адресам. – user1956609

+0

Действительно. Здесь тоже выглядит неверно: 'x2 = my_func (& x [n/2 + first_pos], & x [first_pos + n-1], n/2 + first_pos, nn/2); ... Мне кажется как эта функция нуждается в * assert (first_pos == 0); * для обеспечения правильного ввода;) – Sebivor

+0

«В конечном итоге вы достигнете n до 3, а индекс будет использовать накопленный first_pos». Я не следую? Когда n <3 возвращается возвращаемое значение, а first_pos не ... что накапливается? – user1956609

Смежные вопросы