CUDA - большое количество и выделение памяти

У меня очень странная ошибка в программе. Я потратил много часов на это, но я не нашел решения. Я написал простую программу, чтобы воспроизвести мою проблему. Может быть, кто-то поможет мне. Я попробовал cuda-memcheck & Каков канонический способ проверки на ошибки с использованием API времени выполнения CUDA? но я не получаю никаких ошибок.

Подробности:

Версия nvcc - V6.0.1

версия gcc - 4.8.1

Полный код:

#include <stdio.h>

__constant__ unsigned long long int bigNumber = 83934243334343;
__device__ bool isFound = false;
__global__ void kernel(int *dev_number) {

    unsigned long long int id = threadIdx.x + (blockIdx.x * blockDim.x);
    while (id < bigNumber && isFound==false) {

        if(id == 10) {
            *dev_number = 4;
            isFound=true;
        }
        id++;
    }
}

int main(int argc, char *argv[]) {
    int number = 0;
    int *dev_number;

    printf("Number: %d\n", number);

    return 0;
}

Компиляция и запуск:

nvcc myprogram.cu
./myprogram

Когда я запускаю эту программу, я не получаю никакого возвращаемого значения. Но когда переменная - bigNumber имеет меньшее значение, или я не использую cudaMalloc & cudaMemcpy, это работает (это означает, что вызывается return 0). Какое соединение должно выделять память для другой переменной с константой bigNumber? В чем проблема?

1 ответ

Решение

Теперь, когда вы изменили код на что-то более разумное, я сразу же получу следующую модификацию:

__device__ volatile bool isFound = false;

volatile квалификатор вынуждает компилятор пропускать любые оптимизации, которые мешали бы каждому потоку читать глобальную копию переменной.

Из документации

Компилятор может оптимизировать операции чтения и записи в глобальную или разделяемую память (например, путем кэширования глобальных операций чтения в регистры или кэш-память L1), если он соблюдает семантику упорядочения памяти в функциях ограничения памяти (Memory Fence Functions) и семантику видимости памяти. функций синхронизации (Synchronization Functions).

Эти оптимизации можно отключить с помощью ключевого слова volatile: если переменная, расположенная в глобальной или разделяемой памяти, объявлена ​​как volatile, компилятор предполагает, что ее значение может быть изменено или использовано в любой момент другим потоком, и поэтому любая ссылка на эту переменную компилируется в фактическая инструкция чтения или записи в памяти.

Если вы не можете использовать volatile квалификатор, тогда только один поток принимает условие раннего выхода (isFound) и все остальные должны зацикливаться очень долго, пока их id значение превышает bigNumber

Другие вопросы по тегам