我有一段pthread代码被列为函数" thread"这里。它基本上创建了许多线程(通常在Xeon Phi上为240,在CPU上为16)然后加入它们。
如果我只调用一次这个线程(),它在CPU和Xeon Phi上都能很好地工作。如果我再一次调用它,它仍可在CPU上正常工作,但pthread_create()将报告"错误22"应该是"无效的参数"每60个线程。
例如,第二次运行的thread()的线程0,线程60,线程120等也是在过程中创建的241,301,361等线程将失败(错误22)。但线程1~59,61~119,121~240等工作完美。
请注意,此问题仅在Xeon Phi上发生。
我已经检查了堆栈大小和参数本身,但我没有找到原因。争论是正确的。
void thread()
{
...
int i, rv;
cpu_set_t set;
arg_t args[nthreads];
pthread_t tid[nthreads];
pthread_attr_t attr;
pthread_barrier_t barrier;
rv = pthread_barrier_init(&barrier, NULL, nthreads);
if(rv != 0)
{
printf("Couldn't create the barrier\n");
exit(EXIT_FAILURE);
}
pthread_attr_init(&attr);
for(i = 0; i < nthreads; i++)
{
int cpu_idx = get_cpu_id(i,nthreads);
DEBUGMSG(1, "Assigning thread-%d to CPU-%d\n", i, cpu_idx);
CPU_ZERO(&set);
CPU_SET(cpu_idx, &set);
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &set);
args[i].tid = i;
args[i].ht = ht;
args[i].barrier = &barrier;
/* assing part of the relR for next thread */
args[i].relR.num_tuples = (i == (nthreads-1)) ? numR : numRthr;
args[i].relR.tuples = relR->tuples + numRthr * i;
numR -= numRthr;
/* assing part of the relS for next thread */
args[i].relS.num_tuples = (i == (nthreads-1)) ? numS : numSthr;
args[i].relS.tuples = relS->tuples + numSthr * i;
numS -= numSthr;
rv = pthread_create(&tid[i], &attr, npo_thread, (void*)&args[i]);
if (rv)
{
printf("ERROR; return code from pthread_create() is %d\n", rv);
printf ("%d %s\n", args[i].tid, strerror(rv));
//exit(-1);
}
}
for(i = 0; i < nthreads; i++)
{
pthread_join(tid[i], NULL);
/* sum up results */
result += args[i].num_results;
}
}
答案 0 :(得分:4)
以下是重现问题并显示代码可能出错的最小示例:
#define _GNU_SOURCE
#include <pthread.h>
#include <err.h>
#include <stdio.h>
void *
foo(void *v)
{
printf("foo\n");
return NULL;
}
int
main(int argc, char **argv)
{
pthread_attr_t attr;
pthread_t thr;
cpu_set_t set;
void *v;
int e;
if (pthread_attr_init(&attr))
err(1, "pthread_attr_init");
CPU_ZERO(&set);
CPU_SET(255, &set);
if (pthread_attr_setaffinity_np(&attr, sizeof(set), &set))
err(1, "pthread_attr_setaffinity_np");
if ((e = pthread_create(&thr, &attr, foo, NULL)))
errx(1, "pthread_create: %d", e);
if (pthread_join(thr, &v))
err(1, "pthread_join");
return 0;
}
正如我在您的问题的评论中推测的那样,pthread_attr_setaffinity_np
不检查cpu集是否理智。相反,错误会在pthread_create
中被捕获。由于github上代码中的cpu_get_id
函数明显被破坏,所以我就开始寻找问题。
在Linux上测试过,但这就是pthread_attr_setaffinity_np
的来源,所以这可能是一个安全的假设。