pthread_create () терпит неудачу (неверный аргумент) каждые 60 потоков на Xeon Phi

У меня есть кусок кода pthread, перечисленный здесь как функция «поток» здесь. Он в основном создает несколько потоков (обычно 240 на Xeon Phi и 16 на CPU) и затем присоединяется к ним.

Если я вызываю этот поток () только один раз, он отлично работает как на процессоре, так и на Xeon Phi. Если я вызову его еще раз, он все равно будет отлично работать на процессоре, но pthread_create () сообщит об «ошибке 22», которая должна быть «недопустимым аргументом» каждые 60 потоков.

Например, поток 0, поток 60, поток 120 и т. Д. 2-го запуска потока (), которые также являются потоками 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;
}
}

1

Решение

Вот минимальный пример, чтобы воспроизвести вашу проблему и показать, где ваш код, скорее всего, пойдет не так:

#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 не проверяет, является ли установленный процессор нормальным. Вместо этого ошибка попадает в pthread_create, Так как cpu_get_id функции в вашем коде на github явно сломаны, вот где я бы начал искать проблему.

Проверено на Linux, но там pthread_attr_setaffinity_np исходит из, так что это, вероятно, безопасное предположение.

4

Другие решения


По вопросам рекламы [email protected]