#c #cuda
#c #cuda
Вопрос:
Я экспериментирую с CUDA и столкнулся с очень странной ошибкой. У меня есть следующие файлы (tl; dr, пропустите их):
main.cpp
#include "main.h"
#include "list.hpp"
void print_graph(Graphamp; g);
void init(Graphamp; g) {
g.list = new List<int>;
for (int j = 0; j < 5; j ) {
g.list->push_back(j 1);
}
}
int main()
{
Graph g;
init(g);
print_graph(g);
delete g.list;
}
main.h
#include "list.hpp"
#ifndef _MAIN_H_
#define _MAIN_H_
struct Graph {
int foo;
double bar;
List<int> *list;
};
#endif
printer.cu
#include "main.h"
#include "list.hpp"
#include <cstdio>
void print_graph(Graphamp; g) {
List<int>::iterator it;
for (it = g.list->begin(); it != g.list->end(); it ) {
printf("%dt", *it);
}
printf("nn");
}
list.hpp
Содержит класс с именем List, похожий на STL list. Из-за его длины код опущен, может быть озвучен здесь: Пользовательский источник списка
Если я скомпилирую и запущу это, я получу ошибку segfault. Это работает, как ожидалось, если я внесу любое из следующих изменений:
- переименовать printer.cu для printer.cc , поэтому nvcc выходит из игры.
- измените порядок определения foo и bar в
struct Graph
(!) - измените тип
bar
(не работает, если я изменяю типfoo
)
По-прежнему не работает, если я добавляю к print_graph префикс __host__
.
Ошибка segfault возникает из-за того, что переменная Graph не поступает в print_graph. Этот элемент списка содержит мусор в памяти, поэтому составление списка завершится ошибкой. (Я не могу передать какое-либо другое значение элемента)
Итак, мой вопрос: что я пропустил? Что, черт возьми, происходит? Спасибо за чтение, любая помощь приветствуется.
Комментарии:
1. Проверьте флаги компилятора выравнивания данных — из описания похоже на классическую проблему с не выровненной структурой.
Ответ №1:
Вопрос о требованиях к выравниванию в структурах обсуждается более подробно в главе 3 руководства по программированию на CUDA. Короткий ответ: передача -malign-double в nvcc должна устранить проблему.
Комментарии:
1. Спасибо за информацию. Как оказалось, я должен передать -malign-double в g во время компиляции main.cpp nvcc передает его автоматически.