Я работал с ссылками на текстуры, когда заметил, что они устарели, я попытался обновить свою тестовую функцию для работы с «новыми» объектами текстуры без привязки с помощью tex1Dfetch, но не смог получить те же результаты.
В настоящее время я изучаю использование текстурной памяти для ускорения моей ахорадовой реализации; Мне удалось заставить tex1D()
работать со ссылками на текстуры, однако я заметил, что они устарели, и решил вместо этого использовать объекты текстуры.
Я получаю очень странное поведение с ядрами, когда пытаюсь использовать результаты каким-либо образом; Я могу сделать results[tidx] = tidx;
без проблем, но results[tidx] = temp + 1;
только когда-либо возвращает значение temp
, а не temp * 3
или любой другой числовой тест, включающий temp
.
Я не вижу логической причины для такого поведения, и примеры документации выглядят достаточно похожими, так что я не вижу, где я ошибся.
Я уже прочитал неправильное поведение CUDA tex1Dfetch () и Новый объект текстуры CUDA - получение неверных данных в 2D-случае, но ни одно из них не связано с моей проблемой.
На всякий случай, если это имеет значение; Я использую CUDA версии 10.0, V10.0.130 с Nvidia GTX 980ti.
#include <iostream>
__global__ void test(cudaTextureObject_t tex ,int* results){
int tidx = threadIdx.y * blockDim.x + threadIdx.x;
unsigned temp = tex1Dfetch<unsigned>(tex, threadIdx.x);
results[tidx] = temp * 3;
}
int main(){
int *host_arr;
const int host_arr_size = 8;
// Create and populate host array
std::cout << "Host:" << std::endl;
cudaMallocHost(&host_arr, host_arr_size*sizeof(int));
for (int i = 0; i < host_arr_size; ++i){
host_arr[i] = i * 2;
std::cout << host_arr[i] << std::endl;
}
// Create resource description
struct cudaResourceDesc resDesc;
resDesc.resType = cudaResourceTypeLinear;
resDesc.res.linear.devPtr = &host_arr;
resDesc.res.linear.sizeInBytes = host_arr_size*sizeof(unsigned);
resDesc.res.linear.desc = cudaCreateChannelDesc<unsigned>();
// Create texture description
struct cudaTextureDesc texDesc;
texDesc.readMode = cudaReadModeElementType;
// Create texture
cudaTextureObject_t tex;
cudaCreateTextureObject(&tex, &resDesc, &texDesc, NULL);
// Allocate results array
int * result_arr;
cudaMalloc(&result_arr, host_arr_size*sizeof(unsigned));
// launch test kernel
test<<<1, host_arr_size>>>(tex, result_arr);
// fetch results
std::cout << "Device:" << std::endl;
cudaMemcpy(host_arr, result_arr, host_arr_size*sizeof(unsigned), cudaMemcpyDeviceToHost);
// print results
for (int i = 0; i < host_arr_size; ++i){
std::cout << host_arr[i] << std::endl;
}
// Tidy Up
cudaDestroyTextureObject(tex);
cudaFreeHost(host_arr);
cudaFree(result_arr);
}
Я ожидал, что вышеприведенное будет работать аналогично приведенному ниже (что работает):
texture<int, 1, cudaReadModeElementType> tex_ref;
cudaArray* cuda_array;
__global__ void test(int* results){
const int tidx = threadIdx.x;
results[tidx] = tex1D(tex_ref, tidx) * 3;
}
int main(){
int *host_arr;
int host_arr_size = 8;
// Create and populate host array
cudaMallocHost((void**)&host_arr, host_arr_size * sizeof(int));
for (int i = 0; i < host_arr_size; ++i){
host_arr[i] = i * 2;
std::cout << host_arr[i] << std::endl;
}
// bind to texture
cudaChannelFormatDesc cuDesc = cudaCreateChannelDesc <int >();
cudaMallocArray(&cuda_array, &cuDesc, host_arr_size);
cudaMemcpyToArray(cuda_array, 0, 0, host_arr , host_arr_size * sizeof(int), cudaMemcpyHostToDevice);
cudaBindTextureToArray(tex_ref , cuda_array);
// Allocate results array
int * result_arr;
cudaMalloc((void**)&result_arr, host_arr_size*sizeof(int));
// launch kernel
test<<<1, host_arr_size>>>(result_arr);
// fetch results
cudaMemcpy(host_arr, result_arr, host_arr_size * sizeof(int), cudaMemcpyDeviceToHost);
// print results
for (int i = 0; i < host_arr_size; ++i){
std::cout << host_arr[i] << std::endl;
}
// Tidy Up
cudaUnbindTexture(tex_ref);
cudaFreeHost(host_arr);
cudaFreeArray(cuda_array);
cudaFree(result_arr);
}
Ожидаемые результаты:
Host:
0
2
4
6
8
10
12
14
Device:
0
6
12
18
24
30
36
42
Фактические результаты:
Host:
0
2
4
6
8
10
12
14
Device:
0
2
4
6
8
10
12
14
Кто-нибудь знает, что на земле идет не так?