Ядра CUDA дают разные результаты на 2 разных графических процессорах (GeForce 8600M GT против Quadro FX 770M)

Я работаю над приложением AES CUDA, и у меня есть ядро, которое выполняет шифрование ECB на графическом процессоре. Чтобы убедиться, что логика алгоритма не изменяется при параллельной работе, я отправляю известный входной тестовый вектор, предоставленный NIST, а затем из кода хоста сравниваю вывод с известным тестовым вектором, предоставленным NIST, с утверждением. Я провел этот тест на своем графическом процессоре NVIDIA, который представляет собой 8600M GT. Работает под Windows 7 и версия драйвера 3.0. В этом сценарии все работает идеально, и утверждение выполняется успешно.

Теперь, когда приложение запущено на Quadro FX 770M. Запускается одно и то же приложение, отправляются те же тестовые векторы, но полученный результат неверен, и утверждение не выполняется!!. Это работает в Linux с той же версией драйвера. Ядра выполняются 256 потоками. Внутри ядер и для пропуска арифметических операций используются предварительно вычисленные таблицы поиска из 256 элементов. Эти таблицы изначально загружаются в глобальную память, 1 поток из 256 потоков, запускающих ядро, совместно загружает 1 элемент таблицы поиска и перемещает этот элемент в новую таблицу поиска в разделяемой памяти, что снижает задержку доступа.

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

Здесь объявляются известные тестовые векторы, поэтому в основном они отправляются в AES_set_encrption, который отвечает за настройку ядра.

void test_vectors ()
{ 

  unsigned char testPlainText[]  = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}; 
     unsigned char testKeyText[] =  {0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77,0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4};
     unsigned char testCipherText[] = {0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8};

 unsigned char out[16] = {0x0};
     //AES Encryption
AES_set_encrption( testPlainText, out, 16, (u32*)testKeyText);

 //Display encrypted data
 printf("\n  GPU Encryption: "); 
 for (int i = 0; i < AES_BLOCK_SIZE; i++)
         printf("%x", out[i]);

 //Assert that the encrypted output is the same as the NIST testCipherText vector 
 assert (memcmp (out, testCipherText, 16) == 0);
}

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

__host__ double AES_set_encrption (... *input_data,...*output_data, .. input_length, ... ckey )

 //Allocate memory in the device and copy the input buffer from the host to the GPU
  CUDA_SAFE_CALL( cudaMalloc( (void **) &d_input_data,input_length ) ); 
  CUDA_SAFE_CALL( cudaMemcpy( (void*)d_input_data, (void*)input_data, input_length, cudaMemcpyHostToDevice ) ); 

     dim3 dimGrid(1);
     dim3 dimBlock(THREAD_X,THREAD_Y); // THREAD_X = 4 & THREAD_Y = 64
  AES_encrypt<<<dimGrid,dimBlock>>>(d_input_data);

     cudaThreadSynchronize();

     //Copy the data processed by the GPU back to the host 
  cudaMemcpy(output_data, d_input_data, input_length, cudaMemcpyDeviceToHost);

  //Free CUDA resources
  CUDA_SAFE_CALL( cudaFree(d_input_data) );
}

И, наконец, внутри ядра у меня есть вычисленный набор раундов AES. Поскольку я думал, что проблема синхронизации была в ядре, я установил __syncthreads(); после каждого раунда или вычислительной операции, чтобы убедиться, что все потоки перемещаются одновременно, чтобы никакие невычисленные значения не могли быть оценены. Но все же это не решило проблему.

Вот результат, когда я использую графический процессор 8600M GT, который работает нормально:

256-битный ключ AES

Тестовые векторы NIST:

Текст жалобы: 6bc1bee22e409f96e93d7e117393172a

Ключ: 603deb1015ca71be2b73aef0857d7781

Зашифрованный текст: f3eed1bdb5d2a03c64b5a7e3db181f8

Шифрование графического процессора: f3eed1bdb5d2a03c64b5a7e3db181f8

Статус теста: пройден

И вот когда я использую Quadro FX 770M и терпит неудачу!!

256-битный ключ AES NIST Test Vectors:

Текст жалобы: 6bc1bee22e409f96e93d7e117393172a

Ключ: 603deb1015ca71be2b73aef0857d7781

Зашифрованный текст: f3eed1bdb5d2a03c64b5a7e3db181f8

Шифрование графического процессора: c837204eb4c1063ed79c77946893b0

Общее утверждение memcmp (out, testCipherText, 16) == 0 выдало ошибку

Статус теста: не пройден

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

Заранее спасибо!!


person Bartzilla    schedule 20.10.2010    source источник
comment
Вы пробовали запускать код в режиме эмуляции?   -  person Paul R    schedule 20.10.2010
comment
Да, я получаю совершенно другой результат, все еще неверный.   -  person Bartzilla    schedule 20.10.2010


Ответы (1)


отказ от ответственности: я ничего не знаю о шифровании AES.

Вы используете двойную точность? Вы, вероятно, знаете, но просто чтобы быть уверенным - я считаю, что обе карты, которые вы используете, имеют вычислительную мощность 1.1, которая не поддерживает двойную точность. Возможно, карты или платформы по-разному конвертируют в одинарную точность...? Кто-нибудь знает? По правде говоря, отклонения с плавающей запятой IEEE хорошо определены, поэтому я был бы удивлен.

person jmilloy    schedule 22.10.2010
comment
Кроме того, я только что присоединился .... как мне добавить комментарий к исходному сообщению (в отличие от добавления ответа)? - person jmilloy; 22.10.2010
comment
Я думаю, вам нужно больше rep для редактирования. Но я дал вам +1, чтобы помочь вам :) - person leppie; 22.10.2010
comment
Привет! Большое спасибо за ваш совет, на самом деле мы могли отследить ошибку, и она действительно не была связана с кодом устройства. Обзор: OpenSSL отвечает за обработку круглых ключей. По какой-то причине версия OpenSSL для Windows обрабатывает ключ раунда, отличный от версии для Linux, поэтому ключи раунда AES отправляются уже другими, что приводит к другому выводу устройства. Мы также пытаемся поймать эту ошибку. Как только мы получим его, я опубликую ответ. Тем не менее, подсказки приветствуются.. Спасибо! - person Bartzilla; 23.10.2010
comment
Эту ошибку, должно быть, оказалось очень трудно поймать. - person void_ptr; 11.06.2015