Я новичок в CUDA и пытаюсь понять суть основного, поэтому я приношу свои извинения, если что-то, что я прошу или говорю, звучит слишком просто. Я написал некоторый серийный код в C для генерации массива со случайными числами и последующего нахождения max в этом массиве.Преобразование программы C в CUDA (максимальное уменьшение)
#include <stdio.h>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#define num 100000
int *arr,max = -1;
int getRand() {
double r1=rand()/(double)RAND_MAX; // Generates value between 0 & 1
return (r1 * num) + 1;
}
void generateRandom(int M) {
int i;
for(i=0;i<M;i++) {
arr[i] = getRand();
}
}
void getMax(int M) {
int i;
for(i=0;i<M;i++) {
if(arr[i] > max)
max = arr[i];
}
}
int main(int argc, char *argv[]){
if (argc == 2) {
int M;
/* initialize random seed: */
srand (time(NULL));
M = atoi(argv[1]);
//int arr[M];
arr = (int*)calloc(M,sizeof(int));;
//printf("M = %d MAX = %d\n", M, RAND_MAX);
generateRandom(M);
getMax(M);
printf("Max value: %d",max);
}
else
printf("Invalid arguments.");
return 0;
}
Теперь я пытаюсь преобразовать этот код в простую программу CUDA. Я попытался просто заставить функцию generateRandom работать как ядро, но у меня возникают проблемы с управлением памятью.
#include <stdio.h>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <cuda.h>
#define num 100000
int *arr,max = -1;
int getRand() {
double r1=rand()/(double)RAND_MAX; // Generates value between 0 & 1
return (r1 * num) + 1;
}
void generateRandom(int M) {
int i;
for(i=0;i<M;i++) {
arr[i] = getRand();
}
}
__global__ void getMax(int M) {
int i;
for(i=0;i<M;i++) {
if(arr[i] > max)
max = arr[i];
}
}
int main(int argc, char *argv[]){
if (argc == 2) {
int M;
/* initialize random seed: */
srand (time(NULL));
M = atoi(argv[1]);
//int arr[M];
arr = (int*)calloc(M,sizeof(int));
//printf("M = %d MAX = %d\n", M, RAND_MAX);
generateRandom(M);
getMax<<<1,1>>>(M);
printf("Max value: %d",max);
}
else
printf("Invalid arguments.");
return 0;
}
В результате этого кода произошли следующие ошибки.
cudabasic.cu(23): warning: a host variable "arr" cannot be directly read in >a device function
cudabasic.cu(23): warning: a host variable "max" cannot be directly read in >a device function
cudabasic.cu(24): warning: a host variable "arr" cannot be directly read in >a device function
cudabasic.cu(24): warning: a host variable "max" cannot be directly written >in a device function
Я гугл ошибки и выяснил, что проблема заключалась в том, что я проходил глобальные переменные ядра и, таким образом, устройство не было в состоянии прочитать его. После онлайн-предложения я попытался решить это, используя указатели вместо передачи фактических переменных, но я все еще получаю ошибки.
#include <stdio.h>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <cuda.h>
#define num 100000
int *arr,max = -1;
int getRand() {
double r1=rand()/(double)RAND_MAX; // Generates value between 0 & 1
return (r1 * num) + 1;
}
void generateRandom(int M) {
int i;
for(i=0;i<M;i++) {
arr[i] = getRand();
}
}
__global__ void getMax(int M, int *dArr, int *dMax) {
int i = threadIdx.x;
int a = dArr[i];
for(i=0;i<M;i++) {
if(a > dMax)
dMax = a;
}
}
int main(int argc, char *argv[]){
if (argc == 2) {
int M;
/* initialize random seed: */
srand (time(NULL));
M = atoi(argv[1]);
//int arr[M];
arr = (int*)calloc(M,sizeof(int));
devArr = (int*)cudaMalloc(M,sizeof(int));
//printf("M = %d MAX = %d\n", M, RAND_MAX);
generateRandom(M);
getMax<<<1,1>>>(M, arr, max);
printf("Max value: %d",max);
}
else
printf("Invalid arguments.");
return 0;
}
cudabasic.cu(24): error: operand types are incompatible ("int" and "int *")
cudabasic.cu(25): error: a value of type "int" cannot be assigned to an >entity of type "int *"
Может кто-то мне точку в правильном направлении, как лучше идти об этом это?
Я новичок в CUDA и стараюсь понять суть, поэтому прошу прощения, если что-то, что я прошу или говорю, звучит слишком просто.
Привет, спасибо за ваши объяснения, они были очень полезны. Причина, по которой я использовал threadIdx.x, состояла в том, что я хочу, чтобы этот код использовал несколько потоков (я думаю, я немного опережал себя). Могли бы вы показать мне, как это можно сделать? Также я попытался посмотреть пример кода, с которым вы связались, но я могу выяснить, где искать код. Сокращение списков страниц - CUDA Parallel Reduction и поддерживаемые версии, но я не понимаю, как просматривать фактический код. – Lesha
Я обновил свое оригинальное сообщение, чтобы включить мою первую попытку, к сожалению, она не очень удалась. Я собираюсь посмотреть, смогу ли я это исправить, но если бы вы могли предложить некоторые советы, которые были бы очень полезными. – Lesha
Выполнение оптовых изменений на ваш вопрос делает мой ответ запутанным для будущих читателей. Я предлагаю задать новый вопрос. SO не предназначен для сеанса чата или для запуска диалогового окна. У вашего «нового» кода все еще есть серьезные недостатки. Например, вы запускаете 64 блока по 1 поток каждый. В этом случае 'threadIdx.x' будет * still * всегда равным нулю. Попытка собрать знания CUDA таким образом очень утомительна. Почему бы не использовать некоторые из материалов, которые я связал? Если бы вы это сделали, вы бы поняли, почему 'threadIdx.x' будет * still * всегда равным нулю в вашем новом коде. –