CUDA, используя memset (или fill или ...) для установки массива с плавающей точкой на максимально возможное значение - PullRequest
4 голосов
/ 27 июля 2011

Редактировать: Спасибо за предыдущие ответы. но на самом деле я хочу сделать это в CUDA, и, очевидно, нет функции Fill для CUDA. Я должен заполнить матрицу один раз для каждого потока, поэтому я хочу убедиться, что я использую самый быстрый способ. Это для цикла мой лучший выбор?

Я хочу установить в матрице с плавающей точкой максимально возможное значение (с плавающей точкой). Как правильно выполнять эту работу?

float *matrix=new float[N*N];

for (int i=0;i<N*N;i++){
        matrix[i*N+j]=999999;
}

Заранее спасибо.

Ответы [ 7 ]

17 голосов
/ 27 июля 2011

Самый простой подход в CUDA - использовать thrust :: fill .Thrust включен в CUDA 4.0 и более поздние версии, или вы можете установить его , если вы используете CUDA 3.2.

#include <thrust/fill.h>
#include <thrust/device_vector.h>
...
thrust::device_vector<float> v(N*N);
thrust::fill(v.begin(), v.end(), std::numeric_limits<float>::max()); // or 999999.f if you prefer

Вы также можете написать чистый код CUDA примерно так:

template <typename T>
__global__ void initMatrix(T *matrix, int width, int height, T val) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;

    for (int i = idx; i < width * height; i += gridDim.x * blockDim.x) {
        matrix[i]=val;
    }
}

int main(void) {
    float *matrix = 0;
    cudaMalloc((void*)&matrix, N*N * sizeof(float));

    int blockSize = 256;
    int numBlocks = (N*N + blockSize - 1) / (N*N);
    initMatrix<<<numBlocks, blockSize>>>(matrix, N, N, 
                                         std::numeric_limits<float>::max()); // or 999999.f if you prefer
}
4 голосов
/ 27 июля 2011

Вам нужно пройтись по массиву и установить для каждого элемента float значение std::numeric_limits<float>::max() в limits ... вы не можете использовать memset для этого, поскольку он устанавливает каждый байт в буфер памяти, а не многобайтовое значение, например, число с плавающей запятой и т. д., для определенного значения.

Таким образом, вы получите код, который выглядит следующим образом, поскольку вы используете только один массив для своей матрицы (т. Е. Вам не нужен второй цикл for):

#include <limits>

float* matrix = new float[N*N];

for (int i=0; i < N*N; i++)
{
    matrix[i] = std::numeric_limits<float>::max();
}

Вторая огромная проблема с вашим запросом состоит в том, что memset принимает целочисленный тип для значения, которое должно быть установлено для каждого байта, поэтому вам нужно будет получить фактическую битовую комбинацию максимального значения с плавающей запятой и использовать что в качестве входа для memset. Но даже это не сработает, поскольку memset может установить для каждого байта в буфере памяти только заданное значение, поэтому, если вы передадите 32-разрядное целочисленное значение, представляющее значение с плавающей запятой, в memset, он будет использовать только младшие 8 бит ... так что, в конце концов, это не просто то, что мы не советуем вам делать, но это невозможно для способа реализации memset. Вы просто не можете использовать memset для инициализации буфера памяти многобайтовых типов с определенным значением, если только вы не хотите обнулять значения или вы делаете какой-то странный хак, который позволяет вам записать одно и то же значение для всех байты, которые составляют многобайтовый тип данных.

3 голосов
/ 27 июля 2011

Используйте std::numeric_limits<float>::max() и std::fill как:

#include <limits>     //for std::numeric_limits<> 
#include <algorithm>  //for std::fill

std::fill(matrix, matrix + N*N, std::numeric_limits<float>::max());

Или std::fill_n как (выглядит лучше):

std::fill_n(matrix, N*N, std::numeric_limits<float>::max());

См. Эту онлайн-документацию:

2 голосов
/ 27 июля 2011

Вместо использования динамической памяти в C ++, используйте vector и наблюдайте, как она делает всю работу за вас:

std::vector<float> matrix(N * N, std::numeric_limits<float>::max());

На самом деле вы даже можете сделать ее 2-мерной матрицейлегко:

std::vector<std::vector<float> > matrix(N, std::vector<float>(N, std::numeric_limits<float>::max()));

2 голосов
/ 27 июля 2011

Я предлагаю легко сделать эту работу, вместо этого используйте std :: fill , который находится в алгоритме заголовке.

std::fill( matrix, matrix + (N*N), 999999 ) ;
1 голос
/ 28 июля 2011

Является ли matrix глобальной памятью или локальной памятью потока?Если он находится в глобальной памяти, и вам нужно только выполнить инициализацию (а не сброс в середине ядра), то вы можете использовать memset с хоста перед запуском ядра.Если оно находится в середине ядра, рассмотрите возможность разбиения ядра на две части, чтобы вы все еще могли использовать cudaMemset.

cudaMemset(matrix,std::numeric_limits<float>::max(),N*N*blockSize);
1 голос
/ 27 июля 2011

C ++ Way:

std::fill(matrix, matrix + N*N, std::numeric_limits<float>::max());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...