Standard deviation with thrust

Hallo,

I will calculate the standard deviation from 10000 values. But i don’t know which thrust function i need for the operation at line nine.

This is pseudocode:

// All Points
int   A_keys[9] = { 1,  1,  1,  2,  3,  3,  4,  4,  4};
float A_vals[9] = {30, 40, 29, 35, 33, 35, 28, 42, 32};
// Averages (I could calculate this successful)
int   B_keys[4] = { 1,  2,  3,  4};
float B_avgs[4] = {33, 35, 34, 36};
int   B_n[4]    = { 3,  1,  2,  3};

float A_avgs[9];
// Here I search a function, that copy the B_avgs-Array into the A_avgs-Array
// Than I would have this:
// A_keys[9] = { 1,  1,  1,  2,  3,  3,  4,  4,  4};
// A_vals[9] = {30, 40, 29, 35, 33, 35, 28, 42, 38};
// A_avgs[9] = {33, 33, 33, 35, 34, 34, 36, 36, 36};

// now i can Calculate it:
float A_diff[9];
thrust::transform(A_vals, A_vals+9, A_avgs, A_diff, thrust::minus<float>()); 
float A_modu[9];
thrust::transform(A_diff, A_diff+9, A_modu, thrust::modulus<float>());
int C_keys[4];
int C_vals[4];
thrust::reduce_by_key(A_keys[9], A_keys[9] + 9, A_modu, C_keys, C_vals, thrust::equal_to<int>, thrust::plus<int>);
// ... and so on. This is than not the problem.

Thank you for your help!
p.s. sorry for my “simple” english :D

Instead of this that you are showing:

// A_avgs[9] = {33, 33, 33, 34, 34, 34, 36, 36, 36};

shouldn’t it be this:

// A_avgs[9] = {33, 33, 33, 35, 34, 34, 36, 36, 36};

?

@txbob: Correct! I have change it…

I believe a thrust permutation iterator combined with a simple copy operation can do what you want.

If you’re not sure what a permutation iterator is, please read the thrust quick start guide.

For this particular case, where the keys are consecutive starting at 1, here’s a simple worked example:

$ cat t949.cu
#include <iostream>
#include <thrust/copy.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/device_vector.h>
#include <thrust/iterator/transform_iterator.h>

using namespace thrust::placeholders;

int main(){

int   A_keys[9] = { 1,  1,  1,  2,  3,  3,  4,  4,  4};
float A_vals[9] = {30, 40, 29, 35, 33, 35, 28, 42, 32};
int   B_keys[4] = { 1,  2,  3,  4};
float B_avgs[4] = {33, 35, 34, 36};

// A_avgs[9] = {33, 33, 33, 35, 34, 34, 36, 36, 36};
thrust::device_vector<int> A_k(A_keys, A_keys+9);
thrust::device_vector<float> A_v(A_vals, A_vals+9);
thrust::device_vector<int> B_k(B_keys, B_keys+4);
thrust::device_vector<float> B_a(B_avgs, B_avgs+4);
thrust::device_vector<float> A_a(A_k.size());

thrust::copy_n(thrust::make_permutation_iterator(B_a.begin(), thrust::make_transform_iterator(A_k.begin(), _1 - 1)), 9, A_a.begin());

thrust::copy_n(A_a.begin(), 9, std::ostream_iterator<float>(std::cout, ","));
std::cout << std::endl;
}
$ nvcc -arch=sm_35 -o t949 t949.cu
$ ./t949
33,33,33,35,34,34,36,36,36,
$

Note that permutation iterator lends itself to inclusion in other thrust algorithms (besides copy) and so it may not be necessary to actually create the A_avgs array in your case (or A_a vector in my case), but instead refer to it via the permutation iterator. This may allow for “fusion” of thrust operations, which is generally beneficial for performance. I haven’t analyzed your whole algorithm to see if this makes sense, however.

thx txbob for the detailed answere.
I would do it with the permutation iterator, but i have simplified my problem for the forum. In my real programm, i have sometime a gab in the B_keys array. And the unique key is build out from to arrays. Here a example:

// Input Values
int   A_keyX[13] = { 1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2};
int   A_keyY[13] = { 1,  1,  1,  2,  3,  3,  1,  1,  1,  3,  4,  4,  4};
float A_vals[13] = {30, 40, 29, 35, 33, 35, 28, 42, 32, 31, 31, 33, 32};
int   B_keyX[6]  = { 1,  1,  1,  2,  2,  2};
int   B_keyY[6]  = { 1,  2,  3,  1,  3,  4};
float B_avgs[6]  = {33, 35, 34, 36, 31, 32};
int   B_n[6]     = { 3,  1,  2,  3,  1,  3};

// Output Values
float A_avgs[13] = {33, 33, 33, 35, 34, 34, 36, 36, 36, 31, 32, 32, 32};

This requirements are comform:

  • The combination from keyX and keyY is a unique key
  • A_key and B_key is in the same order