首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CUDA直方图reduce_by_key缺失

CUDA直方图reduce_by_key缺失
EN

Stack Overflow用户
提问于 2016-01-17 21:30:21
回答 1查看 269关注 0票数 0

我有下面的CUDA推力代码,它使用reduce_by_key将值[0,1024]直方图成256个桶。我希望每个桶都有一个count = 4,但是我看到桶0有256,桶255有3,剩下的有4。

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>

#include <cuda.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>

#include <thrust/device_vector.h>
#include <thrust/extrema.h>
#include <thrust/pair.h>

#define SIZE 1024

struct binFunc {
    const float minVal;
    const float valRange;
    const int numBins;
    binFunc(float _minVal, float _valRange, int _numBins) :
        minVal(_minVal), valRange(_valRange), numBins(_numBins) {}

    __host__ __device__
    int operator()(float v) const {
        int b = int((v - minVal) / valRange * float(numBins));
        return b;
    }
};

int main() {
    thrust::device_vector<float> d_vec(SIZE);
    for (int i = 0; i < SIZE; ++i)
        d_vec[i] = float(i);

    thrust::device_vector<float>::iterator min;
    thrust::device_vector<float>::iterator max;
    thrust::pair<thrust::device_vector<float>::iterator,
            thrust::device_vector<float>::iterator> minmax =
            thrust::minmax_element(d_vec.begin(), d_vec.end());
    min = minmax.first;
    max = minmax.second;
    float minVal = *min;
    float maxVal = *max;

    std::cout << "The minimum value is " << minVal
            << " and the maximum value is " << maxVal << "." << std::endl;

    float valRange = maxVal - minVal;

    std::cout << "The range is " << valRange << "." << std::endl;

    int numBins = 256;

    thrust::device_vector<int> d_binResults(SIZE);
    thrust::transform(d_vec.begin(), d_vec.end(), d_binResults.begin(),
            binFunc(minVal, valRange, numBins));

    thrust::device_vector<int>::iterator d_binResults_iter =
            d_binResults.begin();
    for (int i = 0; i < 10; ++i) {
        int b = *d_binResults_iter;
        printf("d_binResults[%d]=%d\n", i, b);
        d_binResults_iter++;
    }

    std::cout << "The numBins is " << numBins << "." << std::endl;

    thrust::device_vector<int> d_binsKeys(numBins);
    thrust::device_vector<int> d_binsValues(numBins);

    thrust::pair<thrust::device_vector<int>::iterator,
            thrust::device_vector<int>::iterator> keys_and_values =
            thrust::reduce_by_key(d_binResults.begin(), d_binResults.end(),
                    thrust::constant_iterator<int>(1), d_binsKeys.begin(),
                    d_binsValues.begin());

    thrust::device_vector<int>::iterator d_binsKeys_begin_iter =
            d_binsKeys.begin();
    thrust::device_vector<int>::iterator d_binsValues_begin_iter =
            d_binsValues.begin();
    for (int i = 0; i < numBins; ++i) {
        int key = *d_binsKeys_begin_iter;
        int val = *d_binsValues_begin_iter;
        printf("d_binsValues[%d]=(%d,%d)\n", i, key, val);
        d_binsKeys_begin_iter++;
        d_binsValues_begin_iter++;
    }
    return 0;
}

产出的显著部分是:

代码语言:javascript
运行
复制
d_binsValues[0]=(0,256)
d_binsValues[1]=(1,4)
d_binsValues[2]=(2,4)
...
d_binsValues[254]=(254,4)
d_binsValues[255]=(255,3)

那么,桶0有256个元素,桶255有3个元素吗?这里发生了什么事?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-18 23:35:08

如果打印出所有的d_binResults[]值而不是前10个,您将发现最后一个元素(d_binResults[1023])的值为256个!但这是一个无效的bin索引。对于numBins = 256,有效索引为0..255。

这是由于函子中的计算算法而发生的:

代码语言:javascript
运行
复制
    int b = int((v - minVal) / valRange * float(numBins));

插入最后一个元素的相关值时,我们有:

代码语言:javascript
运行
复制
(1023 - 0)/1023*256 = 256

但是256是一个无效的bin索引。结果表明,这破坏了reduce_by_key操作,导致最后一个bin有3个元素,第一个bin被“损坏”。

如果您修复了这个问题,那么您将修复所描述的两个问题(第一个bin有256个元素,最后一个bin有3个)。

作为一个简单的证明,添加这一行代码:

代码语言:javascript
运行
复制
d_binResults[1023] = 255;

在您的thrust::transform操作之后立即。结果是正确的。您如何选择纠正您的bin计算算法取决于您。(通过向valRange添加1,可能是“可修复的”,但这可能意味着您期望的直方图值的一些内容)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34843956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档