我用C编写了一个程序来生成一个带有n个数字的Fibonacci序列,其中每个Fibonacci数由一个单独的线程创建,父线程输出整个产生的Fibonacci序列但是我得到了错误的序列n> 2它有些重写值如果n> 2,则斐波那契序列数组中的最后一个元素为0。如何修复它?请找到下面的代码。
/*============================================================================
Description :The Fibonacci sequence
============================================================================ */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
int n; // size of fibonacci sequence.
int *fibseq; // arry holds the value of each fibonacci term.
int i; // counter for the threads.
void *runn(void *arg);
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("format is:./a.out <intgervalue>\n");
return -1;
} // valdiate num of args.
if (atoi(argv[1]) < 0)
{
printf("%d must be>=0\n", atoi(argv[1]));
return -1;
} // valdiate value of arg1.
n = atoi(argv[1]);
fibseq = (int *)malloc(n * sizeof(int));
pthread_t *threads = (pthread_t *) malloc(n * sizeof(pthread_t));
pthread_attr_t attr; // set of thread attribute
pthread_attr_init(&attr);
for (i = 0; i < n; i++)
{
pthread_create(&threads[i], &attr, runn, NULL);
} // End of creating threads.
int j;
for (j = 0; j < n; j++)
{
pthread_join(threads[j], NULL);
} // End of wating the threads to exit.
// printing fibseq.
printf("The Fibonacci sequence.:");
int k;
for (k = 0; k < n; k++)
{
printf("%d,", fibseq[k]);
} // End of printing fibseq.
return 0;
} // End of main.
void *runn(void *arg)
{
if (i == 0)
{
fibseq[i] = 0;
pthread_exit(0);
} // first fib term
if (i == 1)
{
fibseq[i] = 1;
pthread_exit(0);
} // seconed fib term
else
{
fibseq[0] = 0;
fibseq[1] = 1;
int p, pp, fibp, fibpp;
p = (i - 1);
pp = (i - 2);
fibp = fibseq[p];
// printf("fibseq[%d]%d\n",p,fibp);
fibpp = fibseq[pp];
// printf("fibseq[%d]%d\n",pp,fibpp);
fibseq[i] = fibseq[i - 1] + fibseq[i - 2];
// printf("fibseq[%d]%d,\n",i,fibseq[i]);
pthread_exit(0); // thread exit.
} // End of else
} // End of run.
答案 0 :(得分:1)
我看到这篇文章是从2015年12月开始的,但问题的答案很简单。原因是因为您使用两个单独的for循环来创建和加入您的线程。这是做什么导致i&lt; n线程同时创建和运行* runn函数。这意味着线程不会等待更新数组。
它们应该在一个for循环中,这样thread_join语句在每个循环周期中调节每个线程。正如我在下面所做的那样。
for (i = 0; i < n; i++)
{
pthread_create(&threads[i], &attr, runn, NULL);
pthread_join(threads[i], NULL);
}
现在你的线程一次只能通过你的* runn函数。从而解决您的问题。
在旁注中,您似乎在* runn函数的底部有一些不必要的代码,这不是必需的,只是重做您已经完成的工作。
fibseq[0] = 0; //this is unnecessary, because from your first threads fibseq[0] should
//already equal 0
fibseq[1] = 1; //same for here this value should be equal to 1 already
此外,这是不必要的。虽然如果我理解正确,这用于调试目的吗?
int p, pp, fibp, fibpp;
p = (i - 1);
pp = (i - 2);
fibp = fibseq[p];
// printf("fibseq[%d]%d\n",p,fibp);
fibpp = fibseq[pp];
// printf("fibseq[%d]%d\n",pp,fibpp);
else语句所需的唯一相关代码在这里
fibseq[i] = fibseq[i - 1] + fibseq[i - 2];
pthread_exit(0); // thread exit.
我希望这有助于回答这个问题。
答案 1 :(得分:0)
Fibonnaci序列不适合并行化解决方案。实际上closed-form solution实际上是condition variable并不太难以计算,几乎肯定比基于线程的解决方案更快:
Fn = (φn - ψn) / √5
其中φ = (1 + √5) / 2
和ψ = (1 - √5) / 2
。
修改 - 在我的系统上,n
&gt;的已关闭表单会有所不同71由于累积的舍入错误;使用任意精度库会有所帮助。
但是,如果您决定开展此项工作,则必须牢记以下几点:
除非已计算fibseq[i]
和fibseq[i-1]
,否则无法计算fibseq[i-2]
;您将需要使用mutex暂停执行线程i
,直到线程i-1
和i-2
完成;
您有一个竞争条件,其中main
正在更新i
的值,而线程正在尝试使用i
的值同一时间。您可以使用来同步i
的访问,但老实说,更好的解决方案是将i
的值作为参数传递给线程(传递地址不会有帮助;您将遇到相同的同步问题)。