Mahdi Nejadsahebi Ответов: 1

Конфликтный доступ к памяти в cuda8 (GPU)


Во имя Аллаха

желаю хорошо провести время дорогие друзья

Я работаю над программированием GPU с cuda8, и я новичок.
Я знаю параллельное программирование и работал с конфликтом памяти доступа (состояние гонки) в памяти процессора.

Что я уже пробовал:

Когда мы пронизываем программу в процессоре, если мы делаем это таким образом, мы получим ошибку состояния гонки :

#include <thread>
using namespace std;

int16_t* buffer = nullptr;

void function(int16_t* _buffer){
   _buffer[0] = 1;
}

void main(){
	buffer = new int16_t[10];

	thread threads[10];
	for (int16_t tIndex = 0; tIndex < 10; tIndex++){
		threads[tIndex] = thread(function, buffer);
	}
	for (int16_t tIndex = 0; tIndex < 10; tIndex++){
		threads[tIndex].joinable();
			threads[tIndex].join();
	}
}



Это истинная материя, и мы должны предотвратить возникновение этой проблемы, например, использовать мьютекс или атомарный тип данных.
Проблема в том, что когда я делаю это в Cuda (GPU programming) Намеренно этого не произойдет, я задавался вопросом и хочу знать почему?
Мой код ядра cuda, который я тестировал, таков :

__global__ void CudaKernel(int* _buffer){
	int id = threadIdx.x;
	_buffer[0]++;
}


Я вызывал эту функцию ядра несколько раз, например 1000 или... но конфликт доступа к памяти не был замечен, и только один поток увеличивает значение _buffer[0].
Не могли бы вы объяснить мне, почему?

в моем файле .cu я вызываю ядро, как показано ниже :

dim3 blocks(10, 1, 1);
dim3 grids(1, 1, 1);
CudaKernel <<<1, blocks >>>(cudaBuffer);

//Checking launching error
result = cudaGetLastError();
if (cudaSuccess != result){
    cout << "Launching the kernel has failed. error : " << result << "\n";
    goto end;
}

//Waiting to synchronize all of threads to finish
result = cudaDeviceSynchronize();
if (cudaSuccess != result){
    cout << "Failed to synchronize with error " << result << endl;
    goto end;
}


спасибо в adcance

Jochen Arndt

Я не знаю CUDA, поэтому не могу ответить.

Но я предлагаю использовать более сложную операцию, потому что
_buffer[0]++;
это может быть атомарная операция (одна команда GPU).

Mahdi Nejadsahebi

я также вел себя так, как показано ниже :
_buffer[0] = _buffer[0] + 1;
но проблема есть.

1 Ответов

Рейтинг:
5

Mahdi Nejadsahebi

Да, ты был прав.
Проблема была в операторе.
Я использовал "atomicAdd(& _sum[0], 1);", и это исправлено.
Большое вам спасибо, дорогой друг.