View difference between Paste ID: sfmNi8Ns and dxdf8RZf
SHOW: | | - or go back to the newest paste.
1
/*
2
 * Test code related to
3
 * https://stackoverflow.com/questions/78855895
4
 * Compile with nvcc -lcurand -lnpps file.cu
5
 */
6
7
#include <cuda_runtime.h>
8
#include <curand.h>
9
#include <npp.h>
10
11
#include <thrust/device_vector.h>
12
#include <thrust/scan.h>
13
14
#include <algorithm>
15
// using std::max
16
#include <cstdio>
17
// using std::printf
18
19
20
int main()
21
{
22
    const int vecsize = 1024 * 1024;
23
    const int iterations = 10000;
24
    float* rndvec, *normalized, *inscan, *diffs, *hostvars;
25
    for(float** vec: {&rndvec, &normalized, &inscan, &diffs})
26
        if(cudaMalloc(vec, vecsize * sizeof(float)))
27
            return 1;
28
    /*
29
     * nppsSum_32f and nppsMinMax_32f store their results in device memory.
30
     * We use pinned host memory accessible by both to retrieve it without memcpy.
31
     * But we need a cudaDeviceSynchronize() before accessing the values
32
     */
33
    if(cudaHostAlloc(&hostvars, 3 * sizeof(float), 0))
34
        return 2;
35
    float* sum = hostvars, *min = hostvars + 1, *max = hostvars + 2;
36
    curandGenerator_t gen;
37
    if(curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT) != CURAND_STATUS_SUCCESS)
38
        return 3;
39
    if(curandSetPseudoRandomGeneratorSeed(gen, 0xbad1dea) != CURAND_STATUS_SUCCESS)
40
        return 4;
41
    int sumbufsize, minmaxbufsize;
42
    if(nppsSumGetBufferSize_32f(vecsize, &sumbufsize))
43
        return 5;
44
    if(nppsMinMaxGetBufferSize_32f(vecsize - 1, &minmaxbufsize))
45
        return 6;
46
    Npp8u* nppbuf;
47
    if(cudaMalloc(&nppbuf, std::max({sumbufsize, minmaxbufsize})))
48
        return 7;
49
    for(int i = 0; i < iterations; ++i) {
50
        /* Generate random values range (0..1] */
51
        if(curandGenerateUniform(gen, rndvec, vecsize) != CURAND_STATUS_SUCCESS)
52
            return 8;
53
        /* We want range [0..1) so as a clutch, we subtract the minimum */
54
        if(nppsMinMax_32f(rndvec, vecsize, min, max, nppbuf))
55
            return 9;
56
        if(cudaDeviceSynchronize())
57
            return 10;
58
        if(nppsSubC_32f(rndvec, *min, rndvec, vecsize))
59
            return 11;
60
        /* Normalize so that their sum is 1.0 */
61
        if(nppsSum_32f(rndvec, vecsize, sum, nppbuf))
62
            return 12;
63
        cudaDeviceSynchronize();
64
        if(nppsNormalize_32f(rndvec, normalized, vecsize, 0.f /*subtracted*/, *sum /*divided*/))
65
            return 13;
66
        /* verify normalization */
67
        if(nppsSum_32f(normalized, vecsize, sum, nppbuf))
68
            return 14;
69
        /* perform inscan, a.k.a. partial_sum */
70
        thrust::device_ptr<float> normalized_ptr(normalized);
71
        thrust::device_ptr<float> inscan_ptr(inscan);
72
        thrust::inclusive_scan(normalized_ptr, normalized_ptr + vecsize, inscan_ptr);
73
#     if 1
74
        /*
75
         * Optional fix: Filter numerical noise. We know the value should never decrease,
76
         * so we just force that
77
         */
78
        thrust::inclusive_scan(inscan_ptr, inscan_ptr + vecsize, inscan_ptr, thrust::maximum<float>{});
79
#     endif
80
        /* compute pairwise differences of adjacent values */
81
        if(nppsSub_32f(inscan, inscan + 1, diffs, vecsize - 1))
82
            return 15;
83
        if(nppsMinMax_32f(diffs, vecsize - 1, min, max, nppbuf))
84
            return 16;
85
        cudaDeviceSynchronize();
86
        std::printf("mindiff %g maxdiff %g sum %g\n", *min, *max, *sum);
87
        if(*min < 0.f) /* abort of the result ever gets negative */
88
            return 17;
89
    }
90
    std::puts("No error detected");
91
}
92