Член динамической структуры поврежден при передаче в функцию с использованием CUDA / NVCC

#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 передает его автоматически.