Cuda: архитектура GTX460 и разделение по сетке / блоку / потоку кода - PullRequest
0 голосов
/ 29 апреля 2011

Привет, пока что я понял следующее: GTX460 1GB (GF104) имеет 2GPC с 4 SM каждый, поэтому всего 8SM, 1 из которых отключен, что означает: 7SM («Потоковые мультипроцессоры»).Каждый SM имеет 48 Cuda Cores ( Это то, что мы называем Thread? Так что я не понимаю сейчас: почему эта «сложная» архитектура, а не только как на процессоре, говорит: «Хорошо, у GPU есть N ядер, вот и все!»?

Предположим,У меня есть определенная программа, которая разделена на сетку блоков B и каждого блока потоков T (итого B * T потоков), могу ли я как-то сказать, что один блок всегда подключен к одному SM или нет?Потому что, если бы это было так, это усложнило бы работу кодера, поскольку он должен знать, сколько существует SM, чтобы оптимизировать распараллеливание для каждой видеокарты.Например, когда у меня была бы видеокарта с 8 SM, и моя программа разделяла данные только на сетку из 1 блока с N потоками, я мог использовать только один SM, который не использовал бы все его ресурсы!

Можно ли использовать только некоторые потоки карты при кодировании моей программы?Я бы очень хотел оценить ускорение, запустив мою программу на 1..M Всего потоков, где M - общее количество ядер cuda (если это эквивалентно 'thread'), но как это сделать?Достаточно ли кодировать мою программу так:

cudaKernel<<<1, 1>>>(...)

до

cudaKernel<<<1, M>>>(...)

и запускать ее каждый раз?Единственная проблема, которую я вижу здесь, заключается в следующем: допустим, у меня есть простой пример сложения векторов:

#define SIZE 10
__global__ void vecAdd(float* A, float* B, float* C)
{
   int i = threadIdx.x;
   A[i]=0; 
   B[i]=i;
   C[i] = A[i] + B[i];
}
int main()
{
    int N=SIZE;
    float A[SIZE], B[SIZE], C[SIZE];
    // Kernel invocation

    float *devPtrA;
    float *devPtrB;
    float *devPtrC;
    [...]
    vecAdd<<<1, N>>>(devPtrA, devPtrB, devPtrC);
}

, когда я бы сейчас установил vecAdd<<<1, N>>> в vecAdd<<<1, 1>>>, единственный поток не будет вычислять Cв вектор N-размера, потому что единственный поток будет просто вычислить первое значение A, B и, следовательно, C. Как преодолеть эту проблему, чем?Большое спасибо за разъяснения заранее!Вы мне очень поможете!

1 Ответ

2 голосов
/ 29 апреля 2011

По большей части ответ на большинство вопросов, о которых вы спрашиваете, - нет.Не просто нет, но, черт возьми, нет.

Общая идея большинства программ на GPU заключается в том, что он должен быть неявно масштабируемым - т. Е. Ваш код автоматически использует столько ядер, сколько ему дано.В частности, когда он используется для обработки графики, ядро ​​разделяется между выполнением трех типов шейдеров (вершина, геометрия, фрагмент / пиксель).Таким образом, количество доступных ядер может (и часто будет) изменяться динамически в зависимости от общей нагрузки.

Существует несколько причин, по которым графический процессор организован таким образом, а не как обычный многоядерный процессор.Во-первых, он предназначен в первую очередь для использования в «смущающе параллельных» задачах - достаточно очевидно, что его основная цель - применять подобный код к каждому из большого количества пикселей.Хотя вы не используете его точно так же, как для кода CUDA, это все еще основа дизайна аппаратного обеспечения.Во-вторых, как упоминалось выше, ядра фактически разделены по крайней мере на три разные цели и могут быть разделены на большее (например, графическое приложение, использующее одни ядра, и ваш код CUDA, использующий другие).В-третьих, дополнительная абстракция помогает защитить ваш код от изменений в оборудовании.Он позволяет вам указать только те вычисления, которые вам нужны, и максимально эффективно распланировать их на оборудовании.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...