ここに関数「スレッド」としてリストされている pthread コードがあります。基本的に、多数のスレッド (通常、Xeon Phi では 240、CPU では 16) を作成し、それらを結合します。
この thread() を 1 回だけ呼び出すと、CPU と Xeon Phi の両方で完全に動作します。もう一度呼び出すと、CPU では問題なく動作しますが、pthread_create() は 60 スレッドごとに「無効な引数」である「エラー 22」を報告します。
たとえば、thread() の 2 回目の実行のスレッド 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;
}
}