Dynamic initialization is not supported for __constant__
data, as the error message says. That is by design. The subject line of this question only refers to initialization.
Below is a worked example of dynamically updating statically initialized __constant__
data. The output of the program should look similar to this:
original statically initialized __constant__ data
8.30897212e-01 4.79740888e-01 0.00000000e+00
6.54357791e-01 -4.81248736e-01 0.00000000e+00
1.19936131e-01 9.63664353e-01 0.00000000e+00
4.56928723e-02 -3.27000245e-02 0.00000000e+00
-1.37690589e-01 -9.89536941e-01 0.00000000e+00
-6.41368866e-01 7.48885095e-01 0.00000000e+00
-7.78646052e-01 -6.27253354e-01 0.00000000e+00
-7.27497816e-01 6.50641397e-02 0.00000000e+00
dynamically updating second half of __constant__ data
8.30897212e-01 4.79740888e-01 0.00000000e+00
6.54357791e-01 -4.81248736e-01 0.00000000e+00
1.19936131e-01 9.63664353e-01 0.00000000e+00
4.56928723e-02 -3.27000245e-02 0.00000000e+00
4.09999990e+00 4.19999981e+00 4.30000019e+00
5.09999990e+00 5.19999981e+00 5.30000019e+00
6.09999990e+00 6.19999981e+00 6.30000019e+00
7.09999990e+00 7.19999981e+00 7.30000019e+00
dynamically updating first half __constant__ data
1.00000001e-01 2.00000003e-01 3.00000012e-01
1.10000002e+00 1.20000005e+00 1.29999995e+00
2.09999990e+00 2.20000005e+00 2.29999995e+00
3.09999990e+00 3.20000005e+00 3.29999995e+00
4.09999990e+00 4.19999981e+00 4.30000019e+00
5.09999990e+00 5.19999981e+00 5.30000019e+00
6.09999990e+00 6.19999981e+00 6.30000019e+00
7.09999990e+00 7.19999981e+00 7.30000019e+00
#include <stdio.h>
#define N (8)
typedef struct my_vec3 {
float x;
float y;
float z;
} my_vec3;
__constant__ my_vec3 samples_8[N] =
{
{0.8308972f, 0.4797409f, 0.f},
{0.6543578f, -0.48124874f, 0.f},
{0.11993613f, 0.96366435f, 0.f},
{0.045692872f, -0.032700025f, 0.f},
{-0.13769059f, -0.98953694f, 0.f},
{-0.64136887f, 0.7488851f, 0.f},
{-0.77864605f, -0.62725335f, 0.f},
{-0.7274978f, 0.06506414f, 0.f}
};
__global__ void print_samples (void)
{
for (int i = 0; i < N; i++) {
printf ("% 15.8e %15.8e %15.8e\n",
samples_8[i].x, samples_8[i].y, samples_8[i].z);
}
}
void update_samples (my_vec3 *new_samples, size_t size, int offset)
{
cudaMemcpyToSymbol (samples_8, new_samples, size, offset, cudaMemcpyHostToDevice);
}
int main (void)
{
my_vec3 new_samples_8[N] = {
{0.1f, 0.2f, 0.3f},
{1.1f, 1.2f, 1.3f},
{2.1f, 2.2f, 2.3f},
{3.1f, 3.2f, 3.3f},
{4.1f, 4.2f, 4.3f},
{5.1f, 5.2f, 5.3f},
{6.1f, 6.2f, 6.3f},
{7.1f, 7.2f, 7.3f},
};
printf ("original statically initialized __constant__ data\n");
print_samples<<<1,1>>>();
cudaDeviceSynchronize();
printf ("dynamically updating second half of __constant__ data\n");
update_samples (new_samples_8 + (N/2), (N/2)*sizeof(my_vec3), (N/2)*sizeof(my_vec3));
print_samples<<<1,1>>>();
cudaDeviceSynchronize();
printf ("dynamically updating first half __constant__ data\n");
update_samples (new_samples_8, (N/2)*sizeof(my_vec3), 0);
print_samples<<<1,1>>>();
return EXIT_SUCCESS;
}
Note: Last I checked the documentation (long time ago), __constant__
has file scope linkage. That means the data and the function that updates it via cuda MemcpyToSymbol()
must reside in the same .cu
source file. The updating function then can be called from anywhere passing a pointer to the new data.