parent
efac1b4dea
commit
f193f8d601
@ -1,10 +0,0 @@ |
|||||||
#ifndef TYPES_H |
|
||||||
#define TYPES_H |
|
||||||
|
|
||||||
#ifdef __CUDA_ARCH__ |
|
||||||
#define CPU_GPU_FUNCTION __host__ __device__ |
|
||||||
#else |
|
||||||
#define CPU_GPU_FUNCTION |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif |
|
@ -1,135 +0,0 @@ |
|||||||
#ifndef COMMON_H |
|
||||||
#define COMMON_H |
|
||||||
|
|
||||||
#include "co_types.h" |
|
||||||
#include <cmath> |
|
||||||
#include <algorithm> |
|
||||||
|
|
||||||
#if defined(_OPENMP) |
|
||||||
#include <omp.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
|
|
||||||
#define DISABLE_COPY_AND_ASSIGN(classname) \ |
|
||||||
private:\
|
|
||||||
classname(const classname&) = delete;\
|
|
||||||
classname& operator=(const classname&) = delete; |
|
||||||
|
|
||||||
|
|
||||||
template <typename T> |
|
||||||
CPU_GPU_FUNCTION |
|
||||||
void fill(T* arr, int N, T val) { |
|
||||||
for(int idx = 0; idx < N; ++idx) { |
|
||||||
arr[idx] = val; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
CPU_GPU_FUNCTION |
|
||||||
void fill_zero(T* arr, int N) { |
|
||||||
for(int idx = 0; idx < N; ++idx) { |
|
||||||
arr[idx] = 0; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
CPU_GPU_FUNCTION |
|
||||||
inline T distance_euclidean(const T* q, const T* t, int N) { |
|
||||||
T out = 0; |
|
||||||
for(int idx = 0; idx < N; idx++) { |
|
||||||
T diff = q[idx] - t[idx]; |
|
||||||
out += diff * diff; |
|
||||||
} |
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
CPU_GPU_FUNCTION |
|
||||||
inline T distance_l2(const T* q, const T* t, int N) { |
|
||||||
T out = distance_euclidean(q, t, N); |
|
||||||
out = std::sqrt(out); |
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T> |
|
||||||
struct FillFunctor { |
|
||||||
T* arr; |
|
||||||
const T val; |
|
||||||
|
|
||||||
FillFunctor(T* arr, const T val) : arr(arr), val(val) {} |
|
||||||
CPU_GPU_FUNCTION void operator()(const int idx) { |
|
||||||
arr[idx] = val; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
CPU_GPU_FUNCTION |
|
||||||
T mmin(const T& a, const T& b) { |
|
||||||
#ifdef __CUDA_ARCH__ |
|
||||||
return min(a, b); |
|
||||||
#else |
|
||||||
return std::min(a, b); |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
CPU_GPU_FUNCTION |
|
||||||
T mmax(const T& a, const T& b) { |
|
||||||
#ifdef __CUDA_ARCH__ |
|
||||||
return max(a, b); |
|
||||||
#else |
|
||||||
return std::max(a, b); |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
CPU_GPU_FUNCTION |
|
||||||
T mround(const T& a) { |
|
||||||
#ifdef __CUDA_ARCH__ |
|
||||||
return round(a); |
|
||||||
#else |
|
||||||
return round(a); |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
#ifdef __CUDA_ARCH__ |
|
||||||
#if __CUDA_ARCH__ < 600 |
|
||||||
__device__ double atomicAdd(double* address, double val) |
|
||||||
{ |
|
||||||
unsigned long long int* address_as_ull = |
|
||||||
(unsigned long long int*)address; |
|
||||||
unsigned long long int old = *address_as_ull, assumed; |
|
||||||
|
|
||||||
do { |
|
||||||
assumed = old; |
|
||||||
old = atomicCAS(address_as_ull, assumed, |
|
||||||
__double_as_longlong(val + |
|
||||||
__longlong_as_double(assumed))); |
|
||||||
|
|
||||||
// Note: uses integer comparison to avoid hang in case of NaN (since NaN != NaN)
|
|
||||||
} while (assumed != old); |
|
||||||
|
|
||||||
return __longlong_as_double(old); |
|
||||||
} |
|
||||||
#endif |
|
||||||
#endif |
|
||||||
|
|
||||||
|
|
||||||
template <typename T> |
|
||||||
CPU_GPU_FUNCTION |
|
||||||
void matomic_add(T* addr, T val) { |
|
||||||
#ifdef __CUDA_ARCH__ |
|
||||||
atomicAdd(addr, val); |
|
||||||
#else |
|
||||||
#if defined(_OPENMP) |
|
||||||
#pragma omp atomic |
|
||||||
#endif |
|
||||||
*addr += val; |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
#endif |
|
@ -1,173 +0,0 @@ |
|||||||
#ifndef COMMON_CUDA |
|
||||||
#define COMMON_CUDA |
|
||||||
|
|
||||||
#include <cublas_v2.h> |
|
||||||
#include <stdio.h> |
|
||||||
|
|
||||||
#define DEBUG 0 |
|
||||||
#define CUDA_DEBUG_DEVICE_SYNC 0 |
|
||||||
|
|
||||||
// cuda check for cudaMalloc and so on
|
|
||||||
#define CUDA_CHECK(condition) \ |
|
||||||
/* Code block avoids redefinition of cudaError_t error */ \
|
|
||||||
do { \
|
|
||||||
if(CUDA_DEBUG_DEVICE_SYNC) { cudaDeviceSynchronize(); } \
|
|
||||||
cudaError_t error = condition; \
|
|
||||||
if(error != cudaSuccess) { \
|
|
||||||
printf("%s in %s at %d\n", cudaGetErrorString(error), __FILE__, __LINE__); \
|
|
||||||
exit(-1); \
|
|
||||||
} \
|
|
||||||
} while (0) |
|
||||||
|
|
||||||
/// Get error string for error code.
|
|
||||||
/// @param error
|
|
||||||
inline const char* cublasGetErrorString(cublasStatus_t error) { |
|
||||||
switch (error) { |
|
||||||
case CUBLAS_STATUS_SUCCESS: |
|
||||||
return "CUBLAS_STATUS_SUCCESS"; |
|
||||||
case CUBLAS_STATUS_NOT_INITIALIZED: |
|
||||||
return "CUBLAS_STATUS_NOT_INITIALIZED"; |
|
||||||
case CUBLAS_STATUS_ALLOC_FAILED: |
|
||||||
return "CUBLAS_STATUS_ALLOC_FAILED"; |
|
||||||
case CUBLAS_STATUS_INVALID_VALUE: |
|
||||||
return "CUBLAS_STATUS_INVALID_VALUE"; |
|
||||||
case CUBLAS_STATUS_ARCH_MISMATCH: |
|
||||||
return "CUBLAS_STATUS_ARCH_MISMATCH"; |
|
||||||
case CUBLAS_STATUS_MAPPING_ERROR: |
|
||||||
return "CUBLAS_STATUS_MAPPING_ERROR"; |
|
||||||
case CUBLAS_STATUS_EXECUTION_FAILED: |
|
||||||
return "CUBLAS_STATUS_EXECUTION_FAILED"; |
|
||||||
case CUBLAS_STATUS_INTERNAL_ERROR: |
|
||||||
return "CUBLAS_STATUS_INTERNAL_ERROR"; |
|
||||||
case CUBLAS_STATUS_NOT_SUPPORTED: |
|
||||||
return "CUBLAS_STATUS_NOT_SUPPORTED"; |
|
||||||
case CUBLAS_STATUS_LICENSE_ERROR: |
|
||||||
return "CUBLAS_STATUS_LICENSE_ERROR"; |
|
||||||
} |
|
||||||
return "Unknown cublas status"; |
|
||||||
} |
|
||||||
|
|
||||||
#define CUBLAS_CHECK(condition) \ |
|
||||||
do { \
|
|
||||||
if(CUDA_DEBUG_DEVICE_SYNC) { cudaDeviceSynchronize(); } \
|
|
||||||
cublasStatus_t status = condition; \
|
|
||||||
if(status != CUBLAS_STATUS_SUCCESS) { \
|
|
||||||
printf("%s in %s at %d\n", cublasGetErrorString(status), __FILE__, __LINE__); \
|
|
||||||
exit(-1); \
|
|
||||||
} \
|
|
||||||
} while (0) |
|
||||||
|
|
||||||
// check if there is a error after kernel execution
|
|
||||||
#define CUDA_POST_KERNEL_CHECK \ |
|
||||||
CUDA_CHECK(cudaPeekAtLastError()); \
|
|
||||||
CUDA_CHECK(cudaGetLastError());
|
|
||||||
|
|
||||||
#define CUDA_KERNEL_LOOP(i, n) \ |
|
||||||
for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < (n); i += blockDim.x * gridDim.x) |
|
||||||
|
|
||||||
const int CUDA_NUM_THREADS = 1024; |
|
||||||
|
|
||||||
inline int GET_BLOCKS(const int N, const int N_THREADS=CUDA_NUM_THREADS) { |
|
||||||
return (N + N_THREADS - 1) / N_THREADS; |
|
||||||
} |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
T* device_malloc(long N) { |
|
||||||
T* dptr; |
|
||||||
CUDA_CHECK(cudaMalloc(&dptr, N * sizeof(T))); |
|
||||||
if(DEBUG) { printf("[DEBUG] device_malloc %p, %ld\n", dptr, N); } |
|
||||||
return dptr; |
|
||||||
} |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
void device_free(T* dptr) { |
|
||||||
if(DEBUG) { printf("[DEBUG] device_free %p\n", dptr); } |
|
||||||
CUDA_CHECK(cudaFree(dptr)); |
|
||||||
} |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
void host_to_device(const T* hptr, T* dptr, long N) { |
|
||||||
if(DEBUG) { printf("[DEBUG] host_to_device %p => %p, %ld\n", hptr, dptr, N); } |
|
||||||
CUDA_CHECK(cudaMemcpy(dptr, hptr, N * sizeof(T), cudaMemcpyHostToDevice)); |
|
||||||
} |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
T* host_to_device_malloc(const T* hptr, long N) { |
|
||||||
T* dptr = device_malloc<T>(N); |
|
||||||
host_to_device(hptr, dptr, N); |
|
||||||
return dptr; |
|
||||||
} |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
void device_to_host(const T* dptr, T* hptr, long N) { |
|
||||||
if(DEBUG) { printf("[DEBUG] device_to_host %p => %p, %ld\n", dptr, hptr, N); } |
|
||||||
CUDA_CHECK(cudaMemcpy(hptr, dptr, N * sizeof(T), cudaMemcpyDeviceToHost)); |
|
||||||
} |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
T* device_to_host_malloc(const T* dptr, long N) { |
|
||||||
T* hptr = new T[N]; |
|
||||||
device_to_host(dptr, hptr, N); |
|
||||||
return hptr; |
|
||||||
} |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
void device_to_device(const T* dptr, T* hptr, long N) { |
|
||||||
if(DEBUG) { printf("[DEBUG] device_to_device %p => %p, %ld\n", dptr, hptr, N); } |
|
||||||
CUDA_CHECK(cudaMemcpy(hptr, dptr, N * sizeof(T), cudaMemcpyDeviceToDevice)); |
|
||||||
} |
|
||||||
|
|
||||||
// https://github.com/parallel-forall/code-samples/blob/master/posts/cuda-aware-mpi-example/src/Device.cu
|
|
||||||
// https://github.com/treecode/Bonsai/blob/master/runtime/profiling/derived_atomic_functions.h
|
|
||||||
__device__ __forceinline__ void atomicMaxF(float * const address, const float value) { |
|
||||||
if (*address >= value) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
int * const address_as_i = (int *)address; |
|
||||||
int old = * address_as_i, assumed; |
|
||||||
|
|
||||||
do { |
|
||||||
assumed = old; |
|
||||||
if (__int_as_float(assumed) >= value) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
old = atomicCAS(address_as_i, assumed, __float_as_int(value)); |
|
||||||
} while (assumed != old); |
|
||||||
} |
|
||||||
|
|
||||||
__device__ __forceinline__ void atomicMinF(float * const address, const float value) { |
|
||||||
if (*address <= value) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
int * const address_as_i = (int *)address; |
|
||||||
int old = * address_as_i, assumed; |
|
||||||
|
|
||||||
do { |
|
||||||
assumed = old; |
|
||||||
if (__int_as_float(assumed) <= value) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
old = atomicCAS(address_as_i, assumed, __float_as_int(value)); |
|
||||||
} while (assumed != old); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
template <typename FunctorT> |
|
||||||
__global__ void iterate_kernel(FunctorT functor, int N) { |
|
||||||
CUDA_KERNEL_LOOP(idx, N) { |
|
||||||
functor(idx); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
template <typename FunctorT> |
|
||||||
void iterate_cuda(FunctorT functor, int N, int N_THREADS=CUDA_NUM_THREADS) { |
|
||||||
iterate_kernel<<<GET_BLOCKS(N, N_THREADS), N_THREADS>>>(functor, N); |
|
||||||
CUDA_POST_KERNEL_CHECK; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
#endif |
|
@ -1,347 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include "common.h" |
|
||||||
|
|
||||||
|
|
||||||
#define CHECK_CUDA(x) AT_ASSERTM(x.type().is_cuda(), #x " must be a CUDA tensor") |
|
||||||
#define CHECK_CONTIGUOUS(x) AT_ASSERTM(x.is_contiguous(), #x " must be contiguous") |
|
||||||
|
|
||||||
#define CHECK_INPUT_CPU(x) CHECK_CONTIGUOUS(x) |
|
||||||
#define CHECK_INPUT_CUDA(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) |
|
||||||
|
|
||||||
|
|
||||||
template <typename T, int dim=3> |
|
||||||
struct NNFunctor { |
|
||||||
const T* in0; // nelem0 x dim
|
|
||||||
const T* in1; // nelem1 x dim
|
|
||||||
const long nelem0; |
|
||||||
const long nelem1; |
|
||||||
long* out; // nelem0
|
|
||||||
|
|
||||||
NNFunctor(const T* in0, const T* in1, long nelem0, long nelem1, long* out) : in0(in0), in1(in1), nelem0(nelem0), nelem1(nelem1), out(out) {} |
|
||||||
|
|
||||||
CPU_GPU_FUNCTION void operator()(long idx0) { |
|
||||||
// idx0 \in [nelem0]
|
|
||||||
|
|
||||||
const T* vec0 = in0 + idx0 * dim; |
|
||||||
|
|
||||||
T min_dist = 1e9; |
|
||||||
long min_arg = -1; |
|
||||||
for(long idx1 = 0; idx1 < nelem1; ++idx1) { |
|
||||||
const T* vec1 = in1 + idx1 * dim; |
|
||||||
T dist = 0; |
|
||||||
for(long didx = 0; didx < dim; ++didx) { |
|
||||||
T diff = vec0[didx] - vec1[didx]; |
|
||||||
dist += diff * diff; |
|
||||||
} |
|
||||||
|
|
||||||
if(dist < min_dist) { |
|
||||||
min_dist = dist; |
|
||||||
min_arg = idx1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
out[idx0] = min_arg; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
struct CrossCheckFunctor { |
|
||||||
const long* in0; // nelem0
|
|
||||||
const long* in1; // nelem1
|
|
||||||
const long nelem0; |
|
||||||
const long nelem1; |
|
||||||
uint8_t* out; // nelem0
|
|
||||||
|
|
||||||
CrossCheckFunctor(const long* in0, const long* in1, long nelem0, long nelem1, uint8_t* out) : in0(in0), in1(in1), nelem0(nelem0), nelem1(nelem1), out(out) {} |
|
||||||
|
|
||||||
CPU_GPU_FUNCTION void operator()(long idx0) { |
|
||||||
// idx0 \in [nelem0]
|
|
||||||
int idx1 = in0[idx0]; |
|
||||||
out[idx0] = idx1 >=0 && in1[idx1] >= 0 && idx0 == in1[idx1]; |
|
||||||
// out[idx0] = idx0 == in1[in0[idx0]];
|
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
template <typename T, int dim=3> |
|
||||||
struct ProjNNFunctor { |
|
||||||
// xyz0, xyz1 in coord sys of 1
|
|
||||||
const T* xyz0; // bs x height x width x 3
|
|
||||||
const T* xyz1; // bs x height x width x 3
|
|
||||||
const T* K; // 3 x 3
|
|
||||||
const long batch_size; |
|
||||||
const long height; |
|
||||||
const long width; |
|
||||||
const long patch_size; |
|
||||||
long* out; // bs x height x width
|
|
||||||
|
|
||||||
ProjNNFunctor(const T* xyz0, const T* xyz1, const T* K, long batch_size, long height, long width, long patch_size, long* out) |
|
||||||
: xyz0(xyz0), xyz1(xyz1), K(K), batch_size(batch_size), height(height), width(width), patch_size(patch_size), out(out) {} |
|
||||||
|
|
||||||
CPU_GPU_FUNCTION void operator()(long idx0) { |
|
||||||
// idx0 \in [0, bs x height x width]
|
|
||||||
|
|
||||||
const long bs = idx0 / (height * width); |
|
||||||
|
|
||||||
const T x = xyz0[idx0 * 3 + 0]; |
|
||||||
const T y = xyz0[idx0 * 3 + 1]; |
|
||||||
const T z = xyz0[idx0 * 3 + 2]; |
|
||||||
const T d = K[6] * x + K[7] * y + K[8] * z; |
|
||||||
const T u = (K[0] * x + K[1] * y + K[2] * z) / d; |
|
||||||
const T v = (K[3] * x + K[4] * y + K[5] * z) / d; |
|
||||||
|
|
||||||
int u0 = u + 0.5; |
|
||||||
int v0 = v + 0.5; |
|
||||||
|
|
||||||
long min_idx1 = -1; |
|
||||||
T min_dist = 1e9; |
|
||||||
for(int pidx = 0; pidx < patch_size*patch_size; ++pidx) { |
|
||||||
int pu = pidx % patch_size; |
|
||||||
int pv = pidx / patch_size; |
|
||||||
|
|
||||||
int u1 = u0 + pu - patch_size/2; |
|
||||||
int v1 = v0 + pv - patch_size/2; |
|
||||||
|
|
||||||
if(u1 >= 0 && v1 >= 0 && u1 < width && v1 < height) { |
|
||||||
const long idx1 = (bs * height + v1) * width + u1; |
|
||||||
const T* xyz1n = xyz1 + idx1 * 3; |
|
||||||
const T d = (x-xyz1n[0]) * (x-xyz1n[0]) + (y-xyz1n[1]) * (y-xyz1n[1]) + (z-xyz1n[2]) * (z-xyz1n[2]); |
|
||||||
if(d < min_dist) { |
|
||||||
min_dist = d; |
|
||||||
min_idx1 = idx1; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
out[idx0] = min_idx1; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
template <typename T, int dim=3> |
|
||||||
struct XCorrVolFunctor { |
|
||||||
const T* in0; // channels x height x width
|
|
||||||
const T* in1; // channels x height x width
|
|
||||||
const long channels; |
|
||||||
const long height; |
|
||||||
const long width; |
|
||||||
const long n_disps; |
|
||||||
const long block_size; |
|
||||||
T* out; // nelem0
|
|
||||||
|
|
||||||
XCorrVolFunctor(const T* in0, const T* in1, long channels, long height, long width, long n_disps, long block_size, T* out) : in0(in0), in1(in1), channels(channels), height(height), width(width), n_disps(n_disps), block_size(block_size), out(out) {} |
|
||||||
|
|
||||||
CPU_GPU_FUNCTION void operator()(long oidx) { |
|
||||||
// idx0 \in [n_disps x height x width]
|
|
||||||
|
|
||||||
auto d = oidx / (height * width); |
|
||||||
auto h = (oidx / width) % height; |
|
||||||
auto w = oidx % width; |
|
||||||
|
|
||||||
long block_size2 = block_size * block_size; |
|
||||||
|
|
||||||
T val = 0; |
|
||||||
for(int c = 0; c < channels; ++c) { |
|
||||||
// compute means
|
|
||||||
T mu0 = 0; |
|
||||||
T mu1 = 0; |
|
||||||
for(int bh = 0; bh < block_size; ++bh) { |
|
||||||
long h0 = h + bh - block_size / 2; |
|
||||||
h0 = mmax(long(0), mmin(height-1, h0)); |
|
||||||
for(int bw = 0; bw < block_size; ++bw) { |
|
||||||
long w0 = w + bw - block_size / 2; |
|
||||||
long w1 = w0 - d; |
|
||||||
w0 = mmax(long(0), mmin(width-1, w0)); |
|
||||||
w1 = mmax(long(0), mmin(width-1, w1)); |
|
||||||
long idx0 = (c * height + h0) * width + w0; |
|
||||||
long idx1 = (c * height + h0) * width + w1; |
|
||||||
mu0 += in0[idx0] / block_size2; |
|
||||||
mu1 += in1[idx1] / block_size2; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// compute stds and dot product
|
|
||||||
T sigma0 = 0; |
|
||||||
T sigma1 = 0; |
|
||||||
T dot = 0; |
|
||||||
for(int bh = 0; bh < block_size; ++bh) { |
|
||||||
long h0 = h + bh - block_size / 2; |
|
||||||
h0 = mmax(long(0), mmin(height-1, h0)); |
|
||||||
for(int bw = 0; bw < block_size; ++bw) { |
|
||||||
long w0 = w + bw - block_size / 2; |
|
||||||
long w1 = w0 - d; |
|
||||||
w0 = mmax(long(0), mmin(width-1, w0)); |
|
||||||
w1 = mmax(long(0), mmin(width-1, w1)); |
|
||||||
long idx0 = (c * height + h0) * width + w0; |
|
||||||
long idx1 = (c * height + h0) * width + w1; |
|
||||||
T v0 = in0[idx0] - mu0; |
|
||||||
T v1 = in1[idx1] - mu1; |
|
||||||
|
|
||||||
dot += v0 * v1; |
|
||||||
sigma0 += v0 * v0; |
|
||||||
sigma1 += v1 * v1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
T norm = sqrt(sigma0 * sigma1) + 1e-8; |
|
||||||
val += dot / norm; |
|
||||||
} |
|
||||||
|
|
||||||
out[oidx] = val; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const int PHOTOMETRIC_LOSS_MSE = 0; |
|
||||||
const int PHOTOMETRIC_LOSS_SAD = 1; |
|
||||||
const int PHOTOMETRIC_LOSS_CENSUS_MSE = 2; |
|
||||||
const int PHOTOMETRIC_LOSS_CENSUS_SAD = 3; |
|
||||||
|
|
||||||
template <typename T, int type> |
|
||||||
struct PhotometricLossForward { |
|
||||||
const T* es; // batch_size x channels x height x width;
|
|
||||||
const T* ta; |
|
||||||
const int block_size; |
|
||||||
const int block_size2; |
|
||||||
const T eps; |
|
||||||
const int batch_size; |
|
||||||
const int channels; |
|
||||||
const int height; |
|
||||||
const int width; |
|
||||||
T* out; // batch_size x channels x height x width;
|
|
||||||
|
|
||||||
PhotometricLossForward(const T* es, const T* ta, int block_size, T eps, int batch_size, int channels, int height, int width, T* out) : |
|
||||||
es(es), ta(ta), block_size(block_size), block_size2(block_size*block_size), eps(eps), batch_size(batch_size), channels(channels), height(height), width(width), out(out) {} |
|
||||||
|
|
||||||
CPU_GPU_FUNCTION void operator()(int outidx) { |
|
||||||
// outidx \in [0, batch_size x height x width]
|
|
||||||
|
|
||||||
int w = outidx % width; |
|
||||||
int h = (outidx / width) % height; |
|
||||||
int n = outidx / (height * width); |
|
||||||
|
|
||||||
T loss = 0; |
|
||||||
for(int bidx = 0; bidx < block_size2; ++bidx) { |
|
||||||
int bh = bidx / block_size; |
|
||||||
int bw = bidx % block_size; |
|
||||||
int h0 = h + bh - block_size / 2; |
|
||||||
int w0 = w + bw - block_size / 2; |
|
||||||
|
|
||||||
h0 = mmin(height-1, mmax(0, h0)); |
|
||||||
w0 = mmin(width-1, mmax(0, w0)); |
|
||||||
|
|
||||||
for(int c = 0; c < channels; ++c) { |
|
||||||
int inidx = ((n * channels + c) * height + h0) * width + w0; |
|
||||||
if(type == PHOTOMETRIC_LOSS_SAD || type == PHOTOMETRIC_LOSS_MSE) { |
|
||||||
T diff = es[inidx] - ta[inidx]; |
|
||||||
if(type == PHOTOMETRIC_LOSS_MSE) { |
|
||||||
loss += diff * diff / block_size2; |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_SAD) { |
|
||||||
loss += fabs(diff) / block_size2; |
|
||||||
} |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_SAD || type == PHOTOMETRIC_LOSS_CENSUS_MSE) { |
|
||||||
int inidxc = ((n * channels + c) * height + h) * width + w; |
|
||||||
T des = es[inidx] - es[inidxc]; |
|
||||||
T dta = ta[inidx] - ta[inidxc]; |
|
||||||
T h_des = 0.5 * (1 + des / sqrt(des * des + eps)); |
|
||||||
T h_dta = 0.5 * (1 + dta / sqrt(dta * dta + eps)); |
|
||||||
T diff = h_des - h_dta; |
|
||||||
// printf("%d,%d %d,%d: des=%f, dta=%f, h_des=%f, h_dta=%f, diff=%f\n", h,w, h0,w0, des,dta, h_des,h_dta, diff);
|
|
||||||
// printf("%d,%d %d,%d: h_des=%f = 0.5 * (1 + %f / %f); %f, %f, %f\n", h,w, h0,w0, h_des, des, sqrt(des * des + eps), des*des, des*des+eps, eps);
|
|
||||||
if(type == PHOTOMETRIC_LOSS_CENSUS_MSE) { |
|
||||||
loss += diff * diff / block_size2; |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_SAD) { |
|
||||||
loss += fabs(diff) / block_size2; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
out[outidx] = loss; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
template <typename T, int type> |
|
||||||
struct PhotometricLossBackward { |
|
||||||
const T* es; // batch_size x channels x height x width;
|
|
||||||
const T* ta; |
|
||||||
const T* grad_out; |
|
||||||
const int block_size; |
|
||||||
const int block_size2; |
|
||||||
const T eps; |
|
||||||
const int batch_size; |
|
||||||
const int channels; |
|
||||||
const int height; |
|
||||||
const int width; |
|
||||||
T* grad_in; // batch_size x channels x height x width;
|
|
||||||
|
|
||||||
PhotometricLossBackward(const T* es, const T* ta, const T* grad_out, int block_size, T eps, int batch_size, int channels, int height, int width, T* grad_in) : |
|
||||||
es(es), ta(ta), grad_out(grad_out), block_size(block_size), block_size2(block_size*block_size), eps(eps), batch_size(batch_size), channels(channels), height(height), width(width), grad_in(grad_in) {} |
|
||||||
|
|
||||||
CPU_GPU_FUNCTION void operator()(int outidx) { |
|
||||||
// outidx \in [0, batch_size x height x width]
|
|
||||||
|
|
||||||
int w = outidx % width; |
|
||||||
int h = (outidx / width) % height; |
|
||||||
int n = outidx / (height * width); |
|
||||||
|
|
||||||
for(int bidx = 0; bidx < block_size2; ++bidx) { |
|
||||||
int bh = bidx / block_size; |
|
||||||
int bw = bidx % block_size; |
|
||||||
int h0 = h + bh - block_size / 2; |
|
||||||
int w0 = w + bw - block_size / 2; |
|
||||||
|
|
||||||
h0 = mmin(height-1, mmax(0, h0)); |
|
||||||
w0 = mmin(width-1, mmax(0, w0)); |
|
||||||
|
|
||||||
const T go = grad_out[outidx]; |
|
||||||
|
|
||||||
for(int c = 0; c < channels; ++c) { |
|
||||||
int inidx = ((n * channels + c) * height + h0) * width + w0; |
|
||||||
if(type == PHOTOMETRIC_LOSS_SAD || type == PHOTOMETRIC_LOSS_MSE) { |
|
||||||
T diff = es[inidx] - ta[inidx]; |
|
||||||
T grad = 0; |
|
||||||
if(type == PHOTOMETRIC_LOSS_MSE) { |
|
||||||
grad = 2 * diff; |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_SAD) { |
|
||||||
grad = diff < 0 ? -1 : (diff > 0 ? 1 : 0); |
|
||||||
} |
|
||||||
grad = grad / block_size2 * go; |
|
||||||
matomic_add(grad_in + inidx, grad); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_SAD || type == PHOTOMETRIC_LOSS_CENSUS_MSE) { |
|
||||||
int inidxc = ((n * channels + c) * height + h) * width + w; |
|
||||||
T des = es[inidx] - es[inidxc]; |
|
||||||
T dta = ta[inidx] - ta[inidxc]; |
|
||||||
T h_des = 0.5 * (1 + des / sqrt(des * des + eps)); |
|
||||||
T h_dta = 0.5 * (1 + dta / sqrt(dta * dta + eps)); |
|
||||||
T diff = h_des - h_dta; |
|
||||||
|
|
||||||
T grad_loss = 0; |
|
||||||
if(type == PHOTOMETRIC_LOSS_CENSUS_MSE) { |
|
||||||
grad_loss = 2 * diff; |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_SAD) { |
|
||||||
grad_loss = diff < 0 ? -1 : (diff > 0 ? 1 : 0); |
|
||||||
} |
|
||||||
grad_loss = grad_loss / block_size2; |
|
||||||
|
|
||||||
T tmp = des * des + eps; |
|
||||||
T grad_heaviside = 0.5 * eps / sqrt(tmp * tmp * tmp); |
|
||||||
|
|
||||||
T grad = go * grad_loss * grad_heaviside; |
|
||||||
matomic_add(grad_in + inidx, grad); |
|
||||||
matomic_add(grad_in + inidxc, -grad); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,198 +0,0 @@ |
|||||||
#include <torch/extension.h> |
|
||||||
|
|
||||||
#include <iostream> |
|
||||||
|
|
||||||
#include "ext.h" |
|
||||||
|
|
||||||
template <typename FunctorT> |
|
||||||
void iterate_cpu(FunctorT functor, int N) { |
|
||||||
for(int idx = 0; idx < N; ++idx) { |
|
||||||
functor(idx); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
at::Tensor nn_cpu(at::Tensor in0, at::Tensor in1) { |
|
||||||
CHECK_INPUT_CPU(in0); |
|
||||||
CHECK_INPUT_CPU(in1); |
|
||||||
|
|
||||||
auto nelem0 = in0.size(0); |
|
||||||
auto nelem1 = in1.size(0); |
|
||||||
auto dim = in0.size(1); |
|
||||||
|
|
||||||
AT_ASSERTM(dim == in1.size(1), "in0 and in1 have to be the same shape"); |
|
||||||
AT_ASSERTM(dim == 3, "dim hast to be 3"); |
|
||||||
AT_ASSERTM(in0.dim() == 2, "in0 has to be N0 x 3"); |
|
||||||
AT_ASSERTM(in1.dim() == 2, "in1 has to be N1 x 3"); |
|
||||||
|
|
||||||
auto out = at::empty({nelem0}, torch::CPU(at::kLong)); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(in0.scalar_type(), "nn", ([&] { |
|
||||||
iterate_cpu( |
|
||||||
NNFunctor<scalar_t>(in0.data<scalar_t>(), in1.data<scalar_t>(), nelem0, nelem1, out.data<long>()), |
|
||||||
nelem0); |
|
||||||
})); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
at::Tensor crosscheck_cpu(at::Tensor in0, at::Tensor in1) { |
|
||||||
CHECK_INPUT_CPU(in0); |
|
||||||
CHECK_INPUT_CPU(in1); |
|
||||||
|
|
||||||
AT_ASSERTM(in0.dim() == 1, ""); |
|
||||||
AT_ASSERTM(in1.dim() == 1, ""); |
|
||||||
|
|
||||||
auto nelem0 = in0.size(0); |
|
||||||
auto nelem1 = in1.size(0); |
|
||||||
|
|
||||||
auto out = at::empty({nelem0}, torch::CPU(at::kByte)); |
|
||||||
|
|
||||||
iterate_cpu( |
|
||||||
CrossCheckFunctor(in0.data<long>(), in1.data<long>(), nelem0, nelem1, out.data<uint8_t>()), |
|
||||||
nelem0); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
at::Tensor proj_nn_cpu(at::Tensor xyz0, at::Tensor xyz1, at::Tensor K, int patch_size) { |
|
||||||
CHECK_INPUT_CPU(xyz0); |
|
||||||
CHECK_INPUT_CPU(xyz1); |
|
||||||
CHECK_INPUT_CPU(K); |
|
||||||
|
|
||||||
auto batch_size = xyz0.size(0); |
|
||||||
auto height = xyz0.size(1); |
|
||||||
auto width = xyz0.size(2); |
|
||||||
|
|
||||||
AT_ASSERTM(xyz0.size(0) == xyz1.size(0), ""); |
|
||||||
AT_ASSERTM(xyz0.size(1) == xyz1.size(1), ""); |
|
||||||
AT_ASSERTM(xyz0.size(2) == xyz1.size(2), ""); |
|
||||||
AT_ASSERTM(xyz0.size(3) == xyz1.size(3), ""); |
|
||||||
AT_ASSERTM(xyz0.size(3) == 3, ""); |
|
||||||
AT_ASSERTM(xyz0.dim() == 4, ""); |
|
||||||
AT_ASSERTM(xyz1.dim() == 4, ""); |
|
||||||
|
|
||||||
auto out = at::empty({batch_size, height, width}, torch::CPU(at::kLong)); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(xyz0.scalar_type(), "proj_nn", ([&] { |
|
||||||
iterate_cpu( |
|
||||||
ProjNNFunctor<scalar_t>(xyz0.data<scalar_t>(), xyz1.data<scalar_t>(), K.data<scalar_t>(), batch_size, height, width, patch_size, out.data<long>()), |
|
||||||
batch_size * height * width); |
|
||||||
})); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
at::Tensor xcorrvol_cpu(at::Tensor in0, at::Tensor in1, int n_disps, int block_size) { |
|
||||||
CHECK_INPUT_CPU(in0); |
|
||||||
CHECK_INPUT_CPU(in1); |
|
||||||
|
|
||||||
auto channels = in0.size(0); |
|
||||||
auto height = in0.size(1); |
|
||||||
auto width = in0.size(2); |
|
||||||
|
|
||||||
auto out = at::empty({n_disps, height, width}, in0.options()); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(in0.scalar_type(), "xcorrvol", ([&] { |
|
||||||
iterate_cpu( |
|
||||||
XCorrVolFunctor<scalar_t>(in0.data<scalar_t>(), in1.data<scalar_t>(), channels, height, width, n_disps, block_size, out.data<scalar_t>()), |
|
||||||
n_disps * height * width); |
|
||||||
})); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
at::Tensor photometric_loss_forward(at::Tensor es, at::Tensor ta, int block_size, int type, float eps) { |
|
||||||
CHECK_INPUT_CPU(es); |
|
||||||
CHECK_INPUT_CPU(ta); |
|
||||||
|
|
||||||
auto batch_size = es.size(0); |
|
||||||
auto channels = es.size(1); |
|
||||||
auto height = es.size(2); |
|
||||||
auto width = es.size(3); |
|
||||||
|
|
||||||
auto out = at::empty({batch_size, 1, height, width}, es.options()); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(es.scalar_type(), "photometric_loss_forward_cpu", ([&] { |
|
||||||
if(type == PHOTOMETRIC_LOSS_MSE) { |
|
||||||
iterate_cpu( |
|
||||||
PhotometricLossForward<scalar_t, PHOTOMETRIC_LOSS_MSE>(es.data<scalar_t>(), ta.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, out.data<scalar_t>()), |
|
||||||
out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_SAD) { |
|
||||||
iterate_cpu( |
|
||||||
PhotometricLossForward<scalar_t, PHOTOMETRIC_LOSS_SAD>(es.data<scalar_t>(), ta.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, out.data<scalar_t>()), |
|
||||||
out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_MSE) { |
|
||||||
iterate_cpu( |
|
||||||
PhotometricLossForward<scalar_t, PHOTOMETRIC_LOSS_CENSUS_MSE>(es.data<scalar_t>(), ta.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, out.data<scalar_t>()), |
|
||||||
out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_SAD) { |
|
||||||
iterate_cpu( |
|
||||||
PhotometricLossForward<scalar_t, PHOTOMETRIC_LOSS_CENSUS_SAD>(es.data<scalar_t>(), ta.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, out.data<scalar_t>()), |
|
||||||
out.numel()); |
|
||||||
} |
|
||||||
})); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
at::Tensor photometric_loss_backward(at::Tensor es, at::Tensor ta, at::Tensor grad_out, int block_size, int type, float eps) { |
|
||||||
CHECK_INPUT_CPU(es); |
|
||||||
CHECK_INPUT_CPU(ta); |
|
||||||
CHECK_INPUT_CPU(grad_out); |
|
||||||
|
|
||||||
auto batch_size = es.size(0); |
|
||||||
auto channels = es.size(1); |
|
||||||
auto height = es.size(2); |
|
||||||
auto width = es.size(3); |
|
||||||
|
|
||||||
CHECK_INPUT_CPU(ta); |
|
||||||
auto grad_in = at::zeros({batch_size, channels, height, width}, grad_out.options()); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(es.scalar_type(), "photometric_loss_backward_cpu", ([&] { |
|
||||||
if(type == PHOTOMETRIC_LOSS_MSE) { |
|
||||||
iterate_cpu( |
|
||||||
PhotometricLossBackward<scalar_t, PHOTOMETRIC_LOSS_MSE>(es.data<scalar_t>(), ta.data<scalar_t>(), grad_out.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, grad_in.data<scalar_t>()), |
|
||||||
grad_out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_SAD) { |
|
||||||
iterate_cpu( |
|
||||||
PhotometricLossBackward<scalar_t, PHOTOMETRIC_LOSS_SAD>(es.data<scalar_t>(), ta.data<scalar_t>(), grad_out.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, grad_in.data<scalar_t>()), |
|
||||||
grad_out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_MSE) { |
|
||||||
iterate_cpu( |
|
||||||
PhotometricLossBackward<scalar_t, PHOTOMETRIC_LOSS_CENSUS_MSE>(es.data<scalar_t>(), ta.data<scalar_t>(), grad_out.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, grad_in.data<scalar_t>()), |
|
||||||
grad_out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_SAD) { |
|
||||||
iterate_cpu( |
|
||||||
PhotometricLossBackward<scalar_t, PHOTOMETRIC_LOSS_CENSUS_SAD>(es.data<scalar_t>(), ta.data<scalar_t>(), grad_out.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, grad_in.data<scalar_t>()), |
|
||||||
grad_out.numel()); |
|
||||||
} |
|
||||||
})); |
|
||||||
|
|
||||||
return grad_in; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { |
|
||||||
m.def("nn_cpu", &nn_cpu, "nn_cpu"); |
|
||||||
m.def("crosscheck_cpu", &crosscheck_cpu, "crosscheck_cpu"); |
|
||||||
m.def("proj_nn_cpu", &proj_nn_cpu, "proj_nn_cpu"); |
|
||||||
|
|
||||||
m.def("xcorrvol_cpu", &xcorrvol_cpu, "xcorrvol_cpu"); |
|
||||||
|
|
||||||
m.def("photometric_loss_forward", &photometric_loss_forward); |
|
||||||
m.def("photometric_loss_backward", &photometric_loss_backward); |
|
||||||
} |
|
@ -1,135 +0,0 @@ |
|||||||
#include <torch/extension.h> |
|
||||||
|
|
||||||
#include <iostream> |
|
||||||
|
|
||||||
#include "ext.h" |
|
||||||
|
|
||||||
void nn_kernel(at::Tensor in0, at::Tensor in1, at::Tensor out); |
|
||||||
|
|
||||||
at::Tensor nn_cuda(at::Tensor in0, at::Tensor in1) { |
|
||||||
CHECK_INPUT_CUDA(in0); |
|
||||||
CHECK_INPUT_CUDA(in1); |
|
||||||
|
|
||||||
auto nelem0 = in0.size(0); |
|
||||||
auto dim = in0.size(1); |
|
||||||
|
|
||||||
AT_ASSERTM(dim == in1.size(1), "in0 and in1 have to be the same shape"); |
|
||||||
AT_ASSERTM(dim == 3, "dim hast to be 3"); |
|
||||||
AT_ASSERTM(in0.dim() == 2, "in0 has to be N0 x 3"); |
|
||||||
AT_ASSERTM(in1.dim() == 2, "in1 has to be N1 x 3"); |
|
||||||
|
|
||||||
auto out = at::empty({nelem0}, torch::CUDA(at::kLong)); |
|
||||||
|
|
||||||
nn_kernel(in0, in1, out); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void crosscheck_kernel(at::Tensor in0, at::Tensor in1, at::Tensor out); |
|
||||||
|
|
||||||
at::Tensor crosscheck_cuda(at::Tensor in0, at::Tensor in1) { |
|
||||||
CHECK_INPUT_CUDA(in0); |
|
||||||
CHECK_INPUT_CUDA(in1); |
|
||||||
|
|
||||||
AT_ASSERTM(in0.dim() == 1, ""); |
|
||||||
AT_ASSERTM(in1.dim() == 1, ""); |
|
||||||
|
|
||||||
auto nelem0 = in0.size(0); |
|
||||||
auto out = at::empty({nelem0}, torch::CUDA(at::kByte)); |
|
||||||
crosscheck_kernel(in0, in1, out); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
void proj_nn_kernel(at::Tensor xyz0, at::Tensor xyz1, at::Tensor K, int patch_size, at::Tensor out); |
|
||||||
|
|
||||||
at::Tensor proj_nn_cuda(at::Tensor xyz0, at::Tensor xyz1, at::Tensor K, int patch_size) { |
|
||||||
CHECK_INPUT_CUDA(xyz0); |
|
||||||
CHECK_INPUT_CUDA(xyz1); |
|
||||||
CHECK_INPUT_CUDA(K); |
|
||||||
|
|
||||||
auto batch_size = xyz0.size(0); |
|
||||||
auto height = xyz0.size(1); |
|
||||||
auto width = xyz0.size(2); |
|
||||||
|
|
||||||
AT_ASSERTM(xyz0.size(0) == xyz1.size(0), ""); |
|
||||||
AT_ASSERTM(xyz0.size(1) == xyz1.size(1), ""); |
|
||||||
AT_ASSERTM(xyz0.size(2) == xyz1.size(2), ""); |
|
||||||
AT_ASSERTM(xyz0.size(3) == xyz1.size(3), ""); |
|
||||||
AT_ASSERTM(xyz0.size(3) == 3, ""); |
|
||||||
AT_ASSERTM(xyz0.dim() == 4, ""); |
|
||||||
AT_ASSERTM(xyz1.dim() == 4, ""); |
|
||||||
|
|
||||||
auto out = at::empty({batch_size, height, width}, torch::CUDA(at::kLong)); |
|
||||||
|
|
||||||
proj_nn_kernel(xyz0, xyz1, K, patch_size, out); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
void xcorrvol_kernel(at::Tensor in0, at::Tensor in1, int n_disps, int block_size, at::Tensor out); |
|
||||||
|
|
||||||
at::Tensor xcorrvol_cuda(at::Tensor in0, at::Tensor in1, int n_disps, int block_size) { |
|
||||||
CHECK_INPUT_CUDA(in0); |
|
||||||
CHECK_INPUT_CUDA(in1); |
|
||||||
|
|
||||||
// auto channels = in0.size(0);
|
|
||||||
auto height = in0.size(1); |
|
||||||
auto width = in0.size(2); |
|
||||||
|
|
||||||
auto out = at::empty({n_disps, height, width}, in0.options()); |
|
||||||
|
|
||||||
xcorrvol_kernel(in0, in1, n_disps, block_size, out); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void photometric_loss_forward_kernel(at::Tensor es, at::Tensor ta, int block_size, int type, float eps, at::Tensor out); |
|
||||||
|
|
||||||
at::Tensor photometric_loss_forward(at::Tensor es, at::Tensor ta, int block_size, int type, float eps) { |
|
||||||
CHECK_INPUT_CUDA(es); |
|
||||||
CHECK_INPUT_CUDA(ta); |
|
||||||
|
|
||||||
auto batch_size = es.size(0); |
|
||||||
auto height = es.size(2); |
|
||||||
auto width = es.size(3); |
|
||||||
|
|
||||||
auto out = at::empty({batch_size, 1, height, width}, es.options()); |
|
||||||
photometric_loss_forward_kernel(es, ta, block_size, type, eps, out); |
|
||||||
|
|
||||||
return out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void photometric_loss_backward_kernel(at::Tensor es, at::Tensor ta, at::Tensor grad_out, int block_size, int type, float eps, at::Tensor grad_in); |
|
||||||
|
|
||||||
at::Tensor photometric_loss_backward(at::Tensor es, at::Tensor ta, at::Tensor grad_out, int block_size, int type, float eps) { |
|
||||||
CHECK_INPUT_CUDA(es); |
|
||||||
CHECK_INPUT_CUDA(ta); |
|
||||||
CHECK_INPUT_CUDA(grad_out); |
|
||||||
|
|
||||||
auto batch_size = es.size(0); |
|
||||||
auto channels = es.size(1); |
|
||||||
auto height = es.size(2); |
|
||||||
auto width = es.size(3); |
|
||||||
|
|
||||||
auto grad_in = at::zeros({batch_size, channels, height, width}, grad_out.options()); |
|
||||||
photometric_loss_backward_kernel(es, ta, grad_out, block_size, type, eps, grad_in); |
|
||||||
|
|
||||||
return grad_in; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { |
|
||||||
m.def("nn_cuda", &nn_cuda, "nn_cuda"); |
|
||||||
m.def("crosscheck_cuda", &crosscheck_cuda, "crosscheck_cuda"); |
|
||||||
m.def("proj_nn_cuda", &proj_nn_cuda, "proj_nn_cuda"); |
|
||||||
|
|
||||||
m.def("xcorrvol_cuda", &xcorrvol_cuda, "xcorrvol_cuda"); |
|
||||||
|
|
||||||
m.def("photometric_loss_forward", &photometric_loss_forward); |
|
||||||
m.def("photometric_loss_backward", &photometric_loss_backward); |
|
||||||
} |
|
@ -1,112 +0,0 @@ |
|||||||
#include <ATen/ATen.h> |
|
||||||
|
|
||||||
#include "ext.h" |
|
||||||
#include "common_cuda.h" |
|
||||||
|
|
||||||
void nn_kernel(at::Tensor in0, at::Tensor in1, at::Tensor out) { |
|
||||||
auto nelem0 = in0.size(0); |
|
||||||
auto nelem1 = in1.size(0); |
|
||||||
auto dim = in0.size(1); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(in0.scalar_type(), "nn", ([&] { |
|
||||||
iterate_cuda( |
|
||||||
NNFunctor<scalar_t>(in0.data<scalar_t>(), in1.data<scalar_t>(), nelem0, nelem1, out.data<long>()), |
|
||||||
nelem0); |
|
||||||
})); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void crosscheck_kernel(at::Tensor in0, at::Tensor in1, at::Tensor out) { |
|
||||||
auto nelem0 = in0.size(0); |
|
||||||
auto nelem1 = in1.size(0); |
|
||||||
|
|
||||||
iterate_cuda( |
|
||||||
CrossCheckFunctor(in0.data<long>(), in1.data<long>(), nelem0, nelem1, out.data<uint8_t>()), |
|
||||||
nelem0); |
|
||||||
} |
|
||||||
|
|
||||||
void proj_nn_kernel(at::Tensor xyz0, at::Tensor xyz1, at::Tensor K, int patch_size, at::Tensor out) { |
|
||||||
auto batch_size = xyz0.size(0); |
|
||||||
auto height = xyz0.size(1); |
|
||||||
auto width = xyz0.size(2); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(xyz0.scalar_type(), "proj_nn", ([&] { |
|
||||||
iterate_cuda( |
|
||||||
ProjNNFunctor<scalar_t>(xyz0.data<scalar_t>(), xyz1.data<scalar_t>(), K.data<scalar_t>(), batch_size, height, width, patch_size, out.data<long>()), |
|
||||||
batch_size * height * width); |
|
||||||
})); |
|
||||||
} |
|
||||||
|
|
||||||
void xcorrvol_kernel(at::Tensor in0, at::Tensor in1, int n_disps, int block_size, at::Tensor out) { |
|
||||||
auto channels = in0.size(0); |
|
||||||
auto height = in0.size(1); |
|
||||||
auto width = in0.size(2); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(in0.scalar_type(), "xcorrvol", ([&] { |
|
||||||
iterate_cuda( |
|
||||||
XCorrVolFunctor<scalar_t>(in0.data<scalar_t>(), in1.data<scalar_t>(), channels, height, width, n_disps, block_size, out.data<scalar_t>()), |
|
||||||
n_disps * height * width, 512); |
|
||||||
})); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void photometric_loss_forward_kernel(at::Tensor es, at::Tensor ta, int block_size, int type, float eps, at::Tensor out) { |
|
||||||
auto batch_size = es.size(0); |
|
||||||
auto channels = es.size(1); |
|
||||||
auto height = es.size(2); |
|
||||||
auto width = es.size(3); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(es.scalar_type(), "photometric_loss_forward_cuda", ([&] { |
|
||||||
if(type == PHOTOMETRIC_LOSS_MSE) { |
|
||||||
iterate_cuda( |
|
||||||
PhotometricLossForward<scalar_t, PHOTOMETRIC_LOSS_MSE>(es.data<scalar_t>(), ta.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, out.data<scalar_t>()), |
|
||||||
out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_SAD) { |
|
||||||
iterate_cuda( |
|
||||||
PhotometricLossForward<scalar_t, PHOTOMETRIC_LOSS_SAD>(es.data<scalar_t>(), ta.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, out.data<scalar_t>()), |
|
||||||
out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_MSE) { |
|
||||||
iterate_cuda( |
|
||||||
PhotometricLossForward<scalar_t, PHOTOMETRIC_LOSS_CENSUS_MSE>(es.data<scalar_t>(), ta.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, out.data<scalar_t>()), |
|
||||||
out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_SAD) { |
|
||||||
iterate_cuda( |
|
||||||
PhotometricLossForward<scalar_t, PHOTOMETRIC_LOSS_CENSUS_SAD>(es.data<scalar_t>(), ta.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, out.data<scalar_t>()), |
|
||||||
out.numel()); |
|
||||||
} |
|
||||||
})); |
|
||||||
} |
|
||||||
|
|
||||||
void photometric_loss_backward_kernel(at::Tensor es, at::Tensor ta, at::Tensor grad_out, int block_size, int type, float eps, at::Tensor grad_in) { |
|
||||||
auto batch_size = es.size(0); |
|
||||||
auto channels = es.size(1); |
|
||||||
auto height = es.size(2); |
|
||||||
auto width = es.size(3); |
|
||||||
|
|
||||||
AT_DISPATCH_FLOATING_TYPES(es.scalar_type(), "photometric_loss_backward_cuda", ([&] { |
|
||||||
if(type == PHOTOMETRIC_LOSS_MSE) { |
|
||||||
iterate_cuda( |
|
||||||
PhotometricLossBackward<scalar_t, PHOTOMETRIC_LOSS_MSE>(es.data<scalar_t>(), ta.data<scalar_t>(), grad_out.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, grad_in.data<scalar_t>()), |
|
||||||
grad_out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_SAD) { |
|
||||||
iterate_cuda( |
|
||||||
PhotometricLossBackward<scalar_t, PHOTOMETRIC_LOSS_SAD>(es.data<scalar_t>(), ta.data<scalar_t>(), grad_out.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, grad_in.data<scalar_t>()), |
|
||||||
grad_out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_MSE) { |
|
||||||
iterate_cuda( |
|
||||||
PhotometricLossBackward<scalar_t, PHOTOMETRIC_LOSS_CENSUS_MSE>(es.data<scalar_t>(), ta.data<scalar_t>(), grad_out.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, grad_in.data<scalar_t>()), |
|
||||||
grad_out.numel()); |
|
||||||
} |
|
||||||
else if(type == PHOTOMETRIC_LOSS_CENSUS_SAD) { |
|
||||||
iterate_cuda( |
|
||||||
PhotometricLossBackward<scalar_t, PHOTOMETRIC_LOSS_CENSUS_SAD>(es.data<scalar_t>(), ta.data<scalar_t>(), grad_out.data<scalar_t>(), block_size, eps, batch_size, channels, height, width, grad_in.data<scalar_t>()), |
|
||||||
grad_out.numel()); |
|
||||||
} |
|
||||||
})); |
|
||||||
} |
|
Loading…
Reference in new issue