理解C中的线程
我有一个C语言的数学函数,它可以计算很多复杂的数学。该函数有一个标题:理解C中的线程,c,multithreading,pthreads,C,Multithreading,Pthreads,我有一个C语言的数学函数,它可以计算很多复杂的数学。该函数有一个标题: double doTheMath(struct example *e, const unsigned int a, const unsigned int b, const unsigned int c) { /* ... lots of math */ } 我想同时调用这个函数100次。我阅读了关于pthreads的文章,认为这是一个很好的解决方案,可以实现我想要实现的目标。我的想
double doTheMath(struct example *e, const unsigned int a,
const unsigned int b, const unsigned int c)
{
/* ... lots of math */
}
我想同时调用这个函数100次。我阅读了关于pthreads
的文章,认为这是一个很好的解决方案,可以实现我想要实现的目标。我的想法如下:
pthread_t tid[100];
pthread_mutex_t lock;
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init failed\n");
return 1;
}
for(i=0; i<100; i++) {
pthread_create(&(tid[i]), NULL, &doTheMath, NULL);
pthread_mutex_lock(&lock);
d += doTheMath(args);
pthread_mutex_unlock(&lock);
}
pthread_mutex_destroy(&lock);
它将创建我的100个线程(我的机器肯定能够运行),我不需要互斥,所以它将同时调用我的函数100次
cPU核心呢?当我这样做的时候,我所有的CPU核心都会满负荷吗
只有一个函数调用将只加载我CPU的一个核心,创建并运行100个(或更多)线程,调用我的函数将加载我所有的CPU核心-我在这里吗
如何传递给doTheMath它需要的所有参数
您必须创建一个代理函数,该函数具有pthread\u create
可接受的签名,该签名调用其主体中的实际函数:
struct doTheMathArgs {
struct example *e;
const unsigned int a, b, c;
};
callDoTheMath(void *data) {
struct doTheMathArgs *args = data;
doTheMath(args->e, args->a, args->b, args->c);
}
...
struct doTheMathArgs dtma;
dtma.e = ...;
...
dtma.c = ...;
pthread_create(&(tid[i]), NULL, &callDoTheMath, (void *) &dtma);
在这里使用线程真的有意义吗?这会像我希望的那样工作吗?我真的无法理解,当我用互斥锁锁定我的函数调用时,它不会允许同时调用我的函数100次,对吗?那我该怎么做呢
除非你在一台一次能运行100个线程的计算机上工作,否则你的代码会减慢整个过程。你应该选择你的maschine能够运行的多个线程
要回答问题的进一步部分,您必须告诉我们您的doTheMath
函数是如何工作的。此函数的每次调用是否完全独立于其他调用?调用顺序重要吗
如何传递给doTheMath它需要的所有参数
您必须创建一个代理函数,该函数具有pthread\u create
可接受的签名,该签名调用其主体中的实际函数:
struct doTheMathArgs {
struct example *e;
const unsigned int a, b, c;
};
callDoTheMath(void *data) {
struct doTheMathArgs *args = data;
doTheMath(args->e, args->a, args->b, args->c);
}
...
struct doTheMathArgs dtma;
dtma.e = ...;
...
dtma.c = ...;
pthread_create(&(tid[i]), NULL, &callDoTheMath, (void *) &dtma);
在这里使用线程真的有意义吗?这会像我希望的那样工作吗?我真的无法理解,当我用互斥锁锁定我的函数调用时,它不会允许同时调用我的函数100次,对吗?那我该怎么做呢
除非你在一台一次能运行100个线程的计算机上工作,否则你的代码会减慢整个过程。你应该选择你的maschine能够运行的多个线程
要回答问题的进一步部分,您必须告诉我们您的
doTheMath
函数是如何工作的。此函数的每次调用是否完全独立于其他调用?调用顺序重要吗?是的,您可以通过线程来实现这一点。调用它100次是否真的会加快速度是一个单独的问题,因为一旦所有CPU内核都已完全加载,尝试一次运行更多的东西可能会降低速度,而不是提高速度,因为处理器缓存效率会降低。对于CPU密集型任务,最佳线程数可能是CPU核心数(或更多)
关于你的具体问题:
Q1:使用phtread\u create
时,最后一个参数是void*arg
,它是传递给线程的不透明指针。您通常会将其用作指向包含要传递的参数的结构的指针。这也可用于返回计算的总和。请注意,您必须将do\u math
包装在合适的第二个函数中,以便其签名(返回值和参数)与pthread\u create
所期望的一样
问题2。请参见上面的一般警告,因为线程太多,但使用这是一种有用的技术
具体而言:
- 您不希望以目前的方式使用互斥锁。互斥仅用于保护访问公共数据的部分代码(关键部分)
- 您可以创建一个线程来调用
doTheMath
,然后也可以直接从主线程调用doTheMath
。这是不正确的。相反,您应该只创建所有线程(在一个循环中),然后运行另一个循环以等待每个线程完成,并对返回的答案求和
是的,您可以使用线程执行此操作。调用它100次是否真的会加快速度是一个单独的问题,因为一旦所有CPU内核都已完全加载,尝试一次运行更多的东西可能会降低速度,而不是提高速度,因为处理器缓存效率会降低。对于CPU密集型任务,最佳线程数可能是CPU核心数(或更多)
关于你的具体问题:
Q1:使用phtread\u create
时,最后一个参数是void*arg
,它是传递给线程的不透明指针。您通常会将其用作指向包含要传递的参数的结构的指针。这也可用于返回计算的总和。请注意,您必须将do\u math
包装在合适的第二个函数中,以便其签名(返回值和参数)与pthread\u create
所期望的一样
问题2。请参见上面的一般警告,因为线程太多,但使用这是一种有用的技术
具体而言:
- 您不希望以目前的方式使用互斥锁。互斥仅用于保护访问公共数据的部分代码(关键部分)
- 您可以创建一个线程来调用
doTheMath
,然后也可以直接从主线程调用doTheMath
。这是不正确的。相反,您应该只创建所有线程(在一个循环中),然后运行另一个循环以等待每个线程完成,并对返回的答案求和
这个问题缺少大量重要细节。调用该函数的效果如何?你想对结果做什么?什么是d