Прежде всего, запустите программу, используя 1 нить. Чтобы сделать это, построить task_scheduler_init
как первое дело main
, как это:
#include "tbb/tbb.h"
int main() {
tbb::task_scheduler_init init(1);
...
}
Обязательно компилировать с макро TBB_USE_DEBUG
набором 1, так что проверка Т будет включена.
Если однопоточная версия работает, но в многопоточной версии нет, рассмотрите возможность использования Intel Inspector для определения условий гонки. Обязательно выполните компиляцию с TBB_USE_THREADING_TOOLS
, чтобы инспектор получил достаточную информацию.
В противном случае я обычно начинаю с добавления утверждений, потому что машина может проверять утверждения намного быстрее, чем я могу читать сообщения журнала. Если я действительно озадачен тем, почему утверждение терпит неудачу, я использую printfs и идентификаторы задач (а не идентификаторы потоков). Самый простой способ создать идентификатор задачи - выделить его путем пошагового увеличения tbb::atomic<size_t>
и сохранения результата в задаче.
Если у меня очень плохой день, а printfs меняют поведение программы, так что ошибка не появляется, я использую «delayed printfs». Настройте аргументы printf в круговом буфере и запустите printf в записях позже после обнаружения сбоя. Обычно для буфера я использую массив структур, содержащих строку формата и несколько значений размера слова, и делаю размер массива равным двум. Тогда для размещения слотов достаточно атомного приращения и маски. Например, примерно следующее:
const size_t bufSize = 1024;
struct record {
const char* format;
void *arg0, *arg1;
};
tbb::atomic<size_t> head;
record buf[bufSize];
void recf(const char* fmt, void* a, void* b) {
record* r = &buf[head++ & bufSize-1];
r->format = fmt;
r->arg0 = a;
r->arg1 = b;
}
void recf(const char* fmt, int a, int b) {
record* r = &buf[head++ & bufSize-1];
r->format = fmt;
r->arg0 = (void*)a;
r->arg1 = (void*)b;
}
В двух подпрограммах recf записываются формат и значения. Кастинг несколько оскорбителен, но на большинстве архитектур вы можете правильно напечатать запись с printf(r->format, r->arg0, r->arg1)
, даже если вторая перегрузка recf
создала запись.
~ ~
Посмотрите на [этой статье] (http://goparallel.sourceforge.net/use-debugging-exception-features-tbb/). –