Циклы в CUDA C ++ имеют ту же семантику, что и в C ++, поэтому где-то в вашем коде должна быть ошибка. Одной из стратегий отладки было бы сделать это на хосте.
Во-первых, поскольку ваш код является скалярным (например, он не содержит вызовов __syncthreads
), вы можете преобразовать его в __host__ __device__
функции.
distance
не содержит специфичных для CUDA идентификаторов или функций, поэтому вы можете просто добавить __host__
:
__host__ __device__ float distance(float* a, float* b, int aIndex, int bIndex);
Чтобы преобразовать вашу функцию search
, поднимите tid
(который зависит от специфических для CUDA идентификаторов threadIndex
и др.) Вне ее в параметр и сделайте ее функцией __host__ __device__
:
__host__ __device__ void search(int tid, float* centroids, float* features, int featureCount, int *votes)
{
if(tid < featureCount)
{
int index = 0;
while (index < N)
{
votes[tid] = index;
int childIndex = index * CHILDREN + 1;
float minValue = FLT_MAX;
if(childIndex >= (N-CHILDREN)) break;
for(int i = 0; i < CHILDREN; i++)
{
int centroidIndex = childIndex + i;
float value = distance(centroids, features, centroidIndex, tid);
if(value < minValue)
{
minValue = value;
index = childIndex + i;
}
}
}
}
}
Теперь напишите функцию __global__
, которая ничего не делает, кроме вычисления tid
и вызова search
:
__global__ void search_kernel(float *centroids, float features, int featureCount, int *votes)
{
int tid = threadIdx.x + blockIdx.x * blockDim.x;
search(tid, centroids, features, featureCount, votes);
}
Поскольку search
теперь __host__ __device__
, вы можете отладить его, вызвав его из ЦП и эмулировав, что будет делать запуск ядра:
for(int tid = 0; tid < featureCount; ++tid)
{
search(tid, centroids, features, featureCount, votes);
}
Он должен висеть на хосте точно так же, как на устройстве. Вставьте printf
внутрь, чтобы узнать, где. Конечно, вы должны быть уверены, что сделали копии своих массивов на стороне хоста, такие как centroids
, потому что хост не может разыменовывать указатели на память устройства.
Несмотря на то, что printf
доступно для использования из __device__
функций с более новым оборудованием, вы можете предпочесть этот подход, потому что вызовы printf
из ядра не фиксируются до после ядро удаляется. Если ядро никогда не выходит из системы (как, по-видимому, в вашем случае), ваши выходные данные отладки никогда не появятся на экране.