Почему статический объявленный массив из 4 символов без знака создает ld.global.u8 при выборке памяти?

Я использую CUDA 5.5 и нахожу поведение компилятора немного странным: если я попытаюсь обратиться к структуре, в которой только данные состоят из 4 символов без знака, она вызовет четыре загрузки u8. Вместо этого, если я использую объединение и загружаю uchar4, он производит желаемую загрузку nc.v4.u8.

этот код создает ld.global.u8 %rs5, [%r32];

        const int wu = 4;
        struct data {
            uchar_t v[wu];           
            CUDA_CALLABLE_MEMBER uchar_t &operator[] (int i) {
                return v[i];
            }
        } fetch[rows];

        for (int i = 0; i < rows; i++) {
            fetch[i] = *((data*)&src[offsetSrc + i*strideSrc]);
        }

Поэтому я должен решить это, поставив объединение для получения желаемого: ld.global.nc.v4.u8 {%rs49, %rs50, %rs51, %rs52}, [%r37];

       const int wu = 4;
       struct data {
            union {
                uchar_t v[wu];
                uchar4 v4;
            };
            CUDA_CALLABLE_MEMBER uchar_t &operator[] (int i) {
                return v[i];
            }
        } fetch[rows];

        for (int i = 0; i < rows; i++) {
            fetch[i].v4 = *((uchar4*)&src[offsetSrc + i*strideSrc]);
        }

person Dredok    schedule 12.06.2013    source источник
comment
а в чем вопрос?   -  person RoBiK    schedule 12.06.2013
comment
вопрос в том, что я не понял, почему компилятор выдает единую загрузку в явно идентичной структуре... Я думал, что компилятор достаточно умен, чтобы знать, что моя структура выровнена (или может быть выровнена). Но я вижу, что проблема возникла из-за косвенности (данные *) против (uchar4 *). Если указатель src был указателем на тип/структуру, выровненную по 4 байтам (например, int*), с исходной структурой, должен ли компилятор производить одну загрузку по 32 байта или четыре загрузки по 8 байт?   -  person Dredok    schedule 13.06.2013
comment
Вопрос в заголовке. И отличный вопрос. +1   -  person harrism    schedule 13.06.2013


Ответы (1)


GPU требует, чтобы все данные были выровнены естественным образом (т. е. 16-битные данные были выровнены по 16-битам, 32-битные данные были выровнены по 32-битам, 64-битные данные были выровнены по 64-битам и т. д.). uchar4 — это структура из четырех символов без знака, выровненная по 32-битному принципу с помощью атрибута выравнивания. Поэтому его можно загрузить одним 32-битным доступом. Массив из четырех беззнаковых символов, с другой стороны, не обязательно имеет 32-битное выравнивание и, следовательно, не может быть загружен одной 32-битной загрузкой. Объединение выравнивается на основе самого строгого выравнивания, требуемого любой из составных частей.

Пользовательские типы данных могут быть согласованы с атрибутом __align__, который описан в Руководство по программированию CUDA

person njuffa    schedule 12.06.2013