The following code compiles (with nvcc test.cu -o test) and runs without error, meaning that std::sin() does work on the device:
#include <cmath>
#include <vector>
#include <cassert>
#include <numeric>
__global__ void map_sin(double* in, double* out, int n) {
const int i = blockIdx.x * 512 + threadIdx.x;
if (i < n) {
out[i] = std::sin(in[i]);
}
}
int main() {
const int n = 1024;
std::vector<double> in(n), out(n);
std::iota(in.begin(), in.end(), 1.);
double *in_, *out_;
cudaMalloc(reinterpret_cast<void**>(&in_), n * sizeof(double));
cudaMemcpy(in_, in.data(), n * sizeof(double), cudaMemcpyHostToDevice);
cudaMalloc(reinterpret_cast<void**>(&out_), n * sizeof(double));
map_sin<<<n / 512, 512>>>(in_, out_, n);
cudaMemcpy(out.data(), out_, n * sizeof(double), cudaMemcpyDeviceToHost);
cudaFree(in_);
cudaFree(out_);
for (int i = 0; i != 10; ++i) {
assert(std::abs(out[i] - std::sin(in[i])) < 1e-3);
}
}
Why? How? According to this answer, CUDA kernels are supposed to be able to call only __device__ functions. Is std::sin() somehow marked __device__ when compiling with nvcc?