mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 19:39:08 +09:00
initial commit
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
*
|
||||
*-----------------------------------------------------------------------*
|
||||
| |
|
||||
| Except where otherwise noted, this work is licensed under a |
|
||||
| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
| International (CC BY-NC-SA 4.0) license. |
|
||||
| |
|
||||
| Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
| |
|
||||
| Author: CXS group, PSI |
|
||||
*-----------------------------------------------------------------------*
|
||||
You may use this code with the following provisions:
|
||||
|
||||
If the code is fully or partially redistributed, or rewritten in another
|
||||
computing language this notice should be included in the redistribution.
|
||||
|
||||
If this code, or subfunctions or parts of it, is used for research in a
|
||||
publication or if it is fully or partially rewritten for another
|
||||
computing language the authors and institution should be acknowledged
|
||||
in written form in the publication: “Data processing was carried out
|
||||
using the “cSAXS matlab package” developed by the CXS group,
|
||||
Paul Scherrer Institut, Switzerland.”
|
||||
Variations on the latter text can be incorporated upon discussion with
|
||||
the CXS group if needed to more specifically reflect the use of the package
|
||||
for the published work.
|
||||
|
||||
A publication that focuses on describing features, or parameters, that
|
||||
are already existing in the code should be first discussed with the
|
||||
authors.
|
||||
|
||||
This code and subroutines are part of a continuous development, they
|
||||
are provided “as they are” without guarantees or liability on part
|
||||
of PSI or the authors. It is the user responsibility to ensure its
|
||||
proper use and the correctness of the results.
|
||||
|
||||
|
||||
* Compilation from Matlab:
|
||||
mex -R2018a 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" add_to_3D_projection_mex.cpp
|
||||
*
|
||||
* Usage from Matlab:
|
||||
|
||||
full_array = (zeros(1000, 1000, 1, 'single'));
|
||||
small_array = (ones(500, 500, 100, 'single'));
|
||||
|
||||
positions = int32([1:100; 1:100])';
|
||||
indices = int32([1:100]); % indices are starting from 1 !!
|
||||
add_values = true; % (DEFAULT)
|
||||
add_to_3D_projection_mex(small_array,full_array,positions, indices,add_values);
|
||||
|
||||
* Matlab version: add_to_3D_projection(full_array, small_array, positions)
|
||||
*
|
||||
*
|
||||
*
|
||||
* results are directly added to full_array, add_values == false => rewrite original values
|
||||
*
|
||||
* This code in matlab:
|
||||
*
|
||||
N_f = size(full_array);
|
||||
N_s = size(small_array);
|
||||
for ii = 1:N_f(3)
|
||||
for i = 1:2
|
||||
ind_f{i} = max(1, 1+positions(ii,i)):min(N_f(i),positions(ii,i)+N_s(i));
|
||||
ind_s{i} = ((ind_f{i}(1)-positions(ii,i))):(ind_f{i}(end)-positions(ii,i));
|
||||
end
|
||||
full_array(ind_f{:},ii) = full_array(ind_f{:},ii) + small_array(ind_s{:},ii);
|
||||
end
|
||||
*
|
||||
*/
|
||||
|
||||
#include "matlab_overload.h"
|
||||
#include "mex.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <omp.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define THREADS 16
|
||||
#define CHUNK 10
|
||||
|
||||
template <typename dtype, bool add_atomic, bool add_values>
|
||||
void inner_loop(dtype * array_full, dtype const * array_small, const mwSize pos_x0, const mwSize pos_y0, const mwSize pos_zs, const mwSize pos_zf, const mwSize Ns_x, const mwSize Ns_y, const mwSize Nf_x, const mwSize Nf_y)
|
||||
{
|
||||
|
||||
mwSize id, col, row, pos_y, pos_x, id_small, id_large, idc_small, idc_large;
|
||||
|
||||
#pragma omp parallel for schedule(static) num_threads(THREADS) private(col, row, pos_x, pos_y, id_small, id_large, idc_small, idc_large)
|
||||
for (col = (pos_x0>=0 ? 0 : -pos_x0) ; col < Ns_x; col++) {
|
||||
pos_x = col + pos_x0;
|
||||
idc_small = col*Ns_y + Ns_y*Ns_x*pos_zs;
|
||||
idc_large = pos_x*Nf_y + Nf_y*Nf_x*pos_zf;
|
||||
|
||||
if (pos_x >= Nf_x )
|
||||
continue;
|
||||
for (row = (pos_y0 >= 0 ? 0 : -pos_y0) ; row < Ns_y; row++) {
|
||||
pos_y = row + pos_y0;
|
||||
if (pos_y >= Nf_y )
|
||||
continue;
|
||||
|
||||
// skip positions that are out of the matrix
|
||||
id_small = row + idc_small;
|
||||
id_large = pos_y + idc_large;
|
||||
|
||||
if (add_atomic && add_values)
|
||||
//Add values to the already provided ones
|
||||
AddData_atomic(array_full[id_large], array_small[id_small]);
|
||||
else if (add_values)
|
||||
// rewrite original values
|
||||
AddData(array_full[id_large], array_small[id_small]);
|
||||
else
|
||||
// rewrite original values
|
||||
SetData(array_full[id_large], array_small[id_small]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename dtype>
|
||||
void add_to_projection(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
|
||||
|
||||
dtype * array_full;
|
||||
dtype const * array_small;
|
||||
|
||||
GetData(prhs[1], array_full);
|
||||
GetData(prhs[0], array_small);
|
||||
|
||||
// check if values should be added or overwritten
|
||||
bool const add_values = nrhs < 5 || mxGetScalar(prhs[4]); // if true, x += y, if false x = y;
|
||||
bool const add_atomic = nrhs < 6 || mxGetScalar(prhs[5]); // if true, correclty deal with overlap between the positions, but it is slow
|
||||
|
||||
mxInt32 const *indices = mxGetInt32s(prhs[3]);
|
||||
mxInt32 const *positions = mxGetInt32s(prhs[2]);
|
||||
|
||||
/* Get dimension of probe and object / small + large array */
|
||||
mwSize const *fdims = mxGetDimensions(prhs[1]);
|
||||
mwSize const Nf_y = fdims[0];
|
||||
mwSize const Nf_x = fdims[1];
|
||||
mwSize const Nf_z = (mxGetNumberOfDimensions(prhs[1]) == 3 ? fdims[2] : 1);
|
||||
|
||||
mwSize const *sdims = mxGetDimensions(prhs[0]);
|
||||
mwSize const Ns_y = sdims[0];
|
||||
mwSize const Ns_x = sdims[1];
|
||||
mwSize const Ns_z = (mxGetNumberOfDimensions(prhs[0]) == 3 ? sdims[2] : 1);
|
||||
|
||||
mwSize const Nid = mxGetNumberOfElements(prhs[3]);
|
||||
mwSize const Npos = mxGetM(prhs[2]);
|
||||
|
||||
if(Npos != Ns_z && Ns_z > 1 )
|
||||
mexErrMsgIdAndTxt("MexError:tomo","The 3rd dim of 1st input argument must be equal to length of positions.");
|
||||
|
||||
if(Nid != Ns_z && Ns_z > 1)
|
||||
mexErrMsgIdAndTxt("MexError:tomo","The 3rd dim of 1st input argument must be equal to length of indices.");
|
||||
|
||||
mwSize id, pos_zs,pos_zf, col, row, pos_y, pos_x, pos_x0, pos_y0 ;
|
||||
mwSize id_small, id_large, idc_small, idc_large;
|
||||
bool out_of_range = false;
|
||||
|
||||
for (id = 0; id < Nid; id++) {
|
||||
if (Nf_z == 1)
|
||||
pos_zf = 0;
|
||||
else
|
||||
pos_zf = indices[id]-1; // distribute the small_array only to defined sliced in the full_array
|
||||
|
||||
if (pos_zf >= Nf_z)
|
||||
{
|
||||
out_of_range = true;
|
||||
continue;
|
||||
}
|
||||
pos_zs = (id < Ns_z ? id : Ns_z-1); // min(id, Nf_z)
|
||||
|
||||
|
||||
pos_x0 = positions[id+Nid];
|
||||
pos_y0 = positions[id];
|
||||
|
||||
if (add_values && add_atomic)
|
||||
inner_loop<dtype,true,true>(array_full, array_small, pos_x0, pos_y0, pos_zs, pos_zf, Ns_x, Ns_y, Nf_x, Nf_y);
|
||||
else if (add_values)
|
||||
inner_loop<dtype,false,true>(array_full, array_small, pos_x0, pos_y0, pos_zs, pos_zf, Ns_x, Ns_y, Nf_x, Nf_y);
|
||||
else
|
||||
inner_loop<dtype,false,false>(array_full, array_small, pos_x0, pos_y0, pos_zs, pos_zf, Ns_x, Ns_y, Nf_x, Nf_y);
|
||||
|
||||
}
|
||||
if (out_of_range)
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Indices are out of range for provided inputs");
|
||||
|
||||
}
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
|
||||
#if MX_HAS_INTERLEAVED_COMPLEX == 0
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Only Matlab R2018a and newer is supported");
|
||||
#endif
|
||||
|
||||
/* Check for proper number of arguments. */
|
||||
if (nrhs <4 || nrhs > 6)
|
||||
mexErrMsgTxt("4-6 input arguments required: add_to_3D_projection_mex(small_array,full_array,positions, indices, add_values=true, add_atomic=true)");
|
||||
else if (nlhs != 0)
|
||||
mexErrMsgTxt("No output argument has to be specified.");
|
||||
|
||||
/* Input must be of type single / uint32 / uint16. */
|
||||
if ( !(mxIsDouble(prhs[0]) || mxIsSingle(prhs[0]) || mxIsUint32(prhs[0]) || mxIsUint16(prhs[0]) || mxIsLogical(prhs[0]) || mxIsUint8(prhs[0]) ) ) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Class of input 1 is not double/single/uint8/uint16/uint32");
|
||||
}
|
||||
if ( (mxGetClassID(prhs[0]) != mxGetClassID (prhs[1])) ) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs arrays are not the same type");
|
||||
}
|
||||
/* Input must be of type int32. */
|
||||
for (int i=2; i<4; i++) {
|
||||
if (mxIsInt32(prhs[i]) != 1) {
|
||||
printf("Input %d is not integer\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
if ((nrhs == 5) && (mxIsLogical(prhs[4]) != 1)) {
|
||||
printf("Input 5 is not logical\n");
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs must be of correct type.");
|
||||
}
|
||||
|
||||
|
||||
if(mxIsComplex(prhs[0]) != mxIsComplex(prhs[1])) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Complexity of the inputs has to be the same");
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ((mxGetNumberOfDimensions(prhs[0]) > 3) || (mxGetNumberOfDimensions(prhs[0]) < 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[1]) > 3) || (mxGetNumberOfDimensions(prhs[1]) < 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[2]) != 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[3]) != 2))
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Wrong number of dimensions in inputs");
|
||||
|
||||
|
||||
if(mxGetN(prhs[2]) != 2 )
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Positions are expected as Nx2 matrix");
|
||||
|
||||
if (mxIsComplex(prhs[0]))
|
||||
switch (mxGetClassID(prhs[0]))
|
||||
{
|
||||
case mxDOUBLE_CLASS: add_to_projection<mxComplexDouble>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxSINGLE_CLASS: add_to_projection<mxComplexSingle>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT32_CLASS: add_to_projection<mxComplexUint32>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT16_CLASS: add_to_projection<mxComplexUint16>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT8_CLASS: add_to_projection<mxComplexUint8>(nlhs, plhs, nrhs, prhs); break;
|
||||
}
|
||||
else
|
||||
switch (mxGetClassID(prhs[0]))
|
||||
{
|
||||
case mxDOUBLE_CLASS: add_to_projection<mxDouble>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxSINGLE_CLASS: add_to_projection<mxSingle>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT32_CLASS: add_to_projection<mxUint32>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT16_CLASS: add_to_projection<mxUint16>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT8_CLASS: add_to_projection<mxUint8>(nlhs, plhs, nrhs, prhs); break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
*
|
||||
**-----------------------------------------------------------------------*
|
||||
| |
|
||||
| Except where otherwise noted, this work is licensed under a |
|
||||
| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
| International (CC BY-NC-SA 4.0) license. |
|
||||
| |
|
||||
| Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
| |
|
||||
| Author: CXS group, PSI |
|
||||
*-----------------------------------------------------------------------*
|
||||
You may use this code with the following provisions:
|
||||
|
||||
If the code is fully or partially redistributed, or rewritten in another
|
||||
computing language this notice should be included in the redistribution.
|
||||
|
||||
If this code, or subfunctions or parts of it, is used for research in a
|
||||
publication or if it is fully or partially rewritten for another
|
||||
computing language the authors and institution should be acknowledged
|
||||
in written form in the publication: “Data processing was carried out
|
||||
using the “cSAXS matlab package” developed by the CXS group,
|
||||
Paul Scherrer Institut, Switzerland.”
|
||||
Variations on the latter text can be incorporated upon discussion with
|
||||
the CXS group if needed to more specifically reflect the use of the package
|
||||
for the published work.
|
||||
|
||||
A publication that focuses on describing features, or parameters, that
|
||||
are already existing in the code should be first discussed with the
|
||||
authors.
|
||||
|
||||
This code and subroutines are part of a continuous development, they
|
||||
are provided “as they are” without guarantees or liability on part
|
||||
of PSI or the authors. It is the user responsibility to ensure its
|
||||
|
||||
|
||||
|
||||
*
|
||||
Compilation from Matlab:
|
||||
mex -R2018a 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" get_from_3D_projection_mex.cpp
|
||||
|
||||
% Usage from Matlab:
|
||||
full_array = (randn(1000, 1000, 1, 'single'));
|
||||
small_array = (ones(500, 500, 100, 'single'));
|
||||
|
||||
positions = int32([1:100; 1:100])';
|
||||
indices = int32([1:100]); % indices are starting from 1 !!
|
||||
tic; get_from_3D_projection_mex(small_array,full_array,positions,indices); toc
|
||||
|
||||
This code in matlab:
|
||||
full_array = randn(100,100,200, 'single');
|
||||
small_array = zeros(50,50,50, 'single');
|
||||
positions = ones(200,2, 'int32');
|
||||
indices = int32(1:50);
|
||||
|
||||
Npix = size(full_array);
|
||||
small_array = zeros(dimensions, 'single');
|
||||
for jj = 1:length(indices)
|
||||
ii = indices(jj)
|
||||
for i = 1:2
|
||||
% limit to the region inside full_array
|
||||
ind_f{i} = max(1,1+positions(ii,i)):min(positions(ii,i)+dimensions(i),Npix(i));
|
||||
% adjust size of the small matrix to correspond
|
||||
ind_s{i} = ((ind_f{i}(1)-positions(ii,i))):(ind_f{i}(end)-positions(ii,i));
|
||||
end
|
||||
small_array(ind_s{:},jj) = full_array(ind_f{:},ii) ;
|
||||
end
|
||||
*/
|
||||
|
||||
#include "matlab_overload.h"
|
||||
#include "mex.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <omp.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#define THREADS 12
|
||||
#define CHUNK 20
|
||||
|
||||
|
||||
|
||||
template <typename dtype>
|
||||
void inner_loop(dtype const * array_full, dtype * array_small, const mwSize pos_x0, const mwSize pos_y0, const mwSize pos_zs, const mwSize pos_zf, const mwSize Ns_x, const mwSize Ns_y, const mwSize Nf_x, const mwSize Nf_y)
|
||||
{
|
||||
|
||||
mwSize id, col, row, pos_y, pos_x, id_small, id_large, idc_small, idc_large;
|
||||
|
||||
#pragma omp parallel for schedule(static) num_threads(THREADS) private(col, row, pos_x, pos_y, id_small, id_large, idc_small, idc_large)
|
||||
for (col = (pos_x0>=0 ? 0 : -pos_x0) ; col < Ns_x; col++) {
|
||||
pos_x = col + pos_x0;
|
||||
idc_small = col*Ns_y + Ns_y*Ns_x*pos_zs;
|
||||
idc_large = pos_x*Nf_y + Nf_y*Nf_x*pos_zf;
|
||||
|
||||
if (pos_x >= Nf_x )
|
||||
continue;
|
||||
|
||||
|
||||
for (row = (pos_y0 >= 0 ? 0 : -pos_y0) ; row < Ns_y; row++) {
|
||||
pos_y = row + pos_y0;
|
||||
if (pos_y >= Nf_y )
|
||||
continue;
|
||||
|
||||
//skip positions that are out of the matrix
|
||||
id_small = row + idc_small;
|
||||
id_large = pos_y + idc_large;
|
||||
|
||||
//rewrite original values
|
||||
SetData(array_small[id_small], array_full[id_large]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename dtype>
|
||||
void get_from_projection(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
dtype const * array_full;
|
||||
dtype * array_small;
|
||||
|
||||
GetData(prhs[1], array_full);
|
||||
GetData(prhs[0], array_small);
|
||||
|
||||
// check if values should be added or overwritten
|
||||
bool const add_values = !((nrhs == 5) && ( !mxGetScalar(prhs[4]) ));
|
||||
|
||||
mxInt32 const *indices = mxGetInt32s(prhs[3]);
|
||||
mxInt32 const *positions = mxGetInt32s(prhs[2]);
|
||||
|
||||
/* Get dimension of probe and object / small + large array */
|
||||
mwSize const *fdims = mxGetDimensions(prhs[1]);
|
||||
mwSize const Nf_y = fdims[0];
|
||||
mwSize const Nf_x = fdims[1];
|
||||
mwSize const Nf_z = (mxGetNumberOfDimensions(prhs[1]) == 3 ? fdims[2] : 1);
|
||||
|
||||
mwSize const *sdims = mxGetDimensions(prhs[0]);
|
||||
mwSize const Ns_y = sdims[0];
|
||||
mwSize const Ns_x = sdims[1];
|
||||
mwSize const Ns_z = (mxGetNumberOfDimensions(prhs[0]) == 3 ? sdims[2] : 1);
|
||||
|
||||
mwSize const Nid = mxGetNumberOfElements(prhs[3]);
|
||||
mwSize const Npos = mxGetM(prhs[2]);
|
||||
|
||||
if(Npos != Ns_z )
|
||||
mexErrMsgIdAndTxt("MexError:tomo","The 3rd dim of 1st input argument must be equal to length of positions.");
|
||||
|
||||
if(Nid != Ns_z)
|
||||
mexErrMsgIdAndTxt("MexError:tomo","The 3rd dim of 1st input argument must be equal to length of indices.");
|
||||
|
||||
mwSize id, pos_zs,pos_zf, col, row, pos_y, pos_x, pos_x0, pos_y0, idc_small, idc_large;
|
||||
mwSize id_small, id_large;
|
||||
bool out_of_range = false;
|
||||
|
||||
// #pragma omp parallel for schedule(dynamic) num_threads(THREADS) private(col, row, pos_x, pos_y, pos_x0, pos_y0, id_small, id_large, pos_zs,pos_zf,id, idc_small, idc_large)
|
||||
for (id = 0; id < Nid; id++) {
|
||||
if (Nf_z == 1)
|
||||
pos_zf = 0;
|
||||
else
|
||||
pos_zf = indices[id]-1; // distribute the small_array only to defined sliced in the full_array
|
||||
|
||||
if (pos_zf > Nf_z)
|
||||
{
|
||||
out_of_range = true;
|
||||
continue;
|
||||
}
|
||||
pos_zs = (id < Ns_z ? id : Ns_z); // min(id, Nf_z)
|
||||
|
||||
|
||||
pos_x0 = positions[id+Nid];
|
||||
pos_y0 = positions[id];
|
||||
|
||||
inner_loop<dtype>(array_full, array_small, pos_x0, pos_y0, pos_zs, pos_zf, Ns_x, Ns_y, Nf_x, Nf_y);
|
||||
|
||||
}
|
||||
if (out_of_range)
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Indices are out of range for provided inputs");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
#if MX_HAS_INTERLEAVED_COMPLEX == 0
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Only Matlab R2018a and newer is supported");
|
||||
#endif
|
||||
|
||||
/* Check for proper number of arguments. */
|
||||
if (nrhs <4 || nrhs > 5)
|
||||
mexErrMsgTxt("4-5 input arguments required: add_to_3D_projection_mex(small_array,full_array,positions, indices, add_values)");
|
||||
else if (nlhs != 0)
|
||||
mexErrMsgTxt("No output argument has to be specified.");
|
||||
|
||||
/* Input must be of type double / single / uint32 / uint16. */
|
||||
if ( !(mxIsDouble(prhs[0]) || mxIsSingle(prhs[0]) || mxIsUint32(prhs[0]) || mxIsUint16(prhs[0]) || mxIsLogical(prhs[0]) || mxIsUint8(prhs[0]) ) ) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Class of input 1 is not double/single/uint8/uint16/uint32");
|
||||
}
|
||||
if ( (mxGetClassID(prhs[0]) != mxGetClassID (prhs[1])) ) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs arrays are not the same type");
|
||||
}
|
||||
/* Input must be of type int32. */
|
||||
for (int i=2; i<4; i++) {
|
||||
if (mxIsInt32(prhs[i]) != 1) {
|
||||
printf("Input %d is not integer\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
|
||||
if(mxIsComplex(prhs[0]) != mxIsComplex(prhs[1])) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Complexity of the inputs has to be the same");
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ((mxGetNumberOfDimensions(prhs[0]) > 3) || (mxGetNumberOfDimensions(prhs[0]) < 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[1]) > 3) || (mxGetNumberOfDimensions(prhs[1]) < 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[2]) != 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[3]) != 2))
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Wrong number of dimensions in inputs");
|
||||
|
||||
if(mxGetN(prhs[2]) != 2 )
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Positions are expected as Nx2 matrix");
|
||||
|
||||
if (mxIsComplex(prhs[0]))
|
||||
switch (mxGetClassID(prhs[0]))
|
||||
{
|
||||
case mxDOUBLE_CLASS: get_from_projection<mxComplexDouble>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxSINGLE_CLASS: get_from_projection<mxComplexSingle>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT32_CLASS: get_from_projection<mxComplexUint32>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT16_CLASS: get_from_projection<mxComplexUint16>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT8_CLASS: get_from_projection<mxComplexUint8>(nlhs, plhs, nrhs, prhs); break;
|
||||
}
|
||||
else
|
||||
switch (mxGetClassID(prhs[0]))
|
||||
{
|
||||
case mxDOUBLE_CLASS: get_from_projection<mxDouble>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxSINGLE_CLASS: get_from_projection<mxSingle>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT32_CLASS: get_from_projection<mxUint32>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT16_CLASS: get_from_projection<mxUint16>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT8_CLASS: get_from_projection<mxUint8>(nlhs, plhs, nrhs, prhs); break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef INTERP3_GPU_tex_HPP
|
||||
#define INTERP3_GPU_tex_HPP
|
||||
|
||||
#include "tmwtypes.h"
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
|
||||
// interp3_gpu.m - fast texture based GPU based interpolation method for 3D deformation
|
||||
//
|
||||
// RECOMPILE: mexcuda -output interp3_gpu_mex interp3_gpu_ker.cu interp3_gpu_mex.cpp
|
||||
//
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// %| |
|
||||
// %| Except where otherwise noted, this work is licensed under a |
|
||||
// %| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
// %| International (CC BY-NC-SA 4.0) license. |
|
||||
// %| |
|
||||
// %| Copyright (c) 2018 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
// %| |
|
||||
// %| Author: CXS group, PSI |
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// % You may use this code with the following provisions:
|
||||
// %
|
||||
// % If the code is fully or partially redistributed, or rewritten in another
|
||||
// % computing language this notice should be included in the redistribution.
|
||||
// %
|
||||
// % If this code, or subfunctions or parts of it, is used for research in a
|
||||
// % publication or if it is fully or partially rewritten for another
|
||||
// % computing language the authors and institution should be acknowledged
|
||||
// % in written form in the publication: “Data processing was carried out
|
||||
// % using the “cSAXS matlab package” developed by the CXS group,
|
||||
// % Paul Scherrer Institut, Switzerland.”
|
||||
// % Variations on the latter text can be incorporated upon discussion with
|
||||
// % the CXS group if needed to more specifically reflect the use of the package
|
||||
// % for the published work.
|
||||
// %
|
||||
// % A publication that focuses on describing features, or parameters, that
|
||||
// % are already existing in the code should be first discussed with the
|
||||
// % authors.
|
||||
// %
|
||||
// % This code and subroutines are part of a continuous development, they
|
||||
// % are provided “as they are” without guarantees or liability on part
|
||||
// % of PSI or the authors. It is the user responsibility to ensure its
|
||||
// % proper use and the correctness of the results.
|
||||
|
||||
|
||||
|
||||
|
||||
int checkLastError(char * msg);
|
||||
|
||||
void interp3_init( float * Img, const mxGPUArray * Img_0, const mxGPUArray *X, const mxGPUArray *Y, const mxGPUArray *Z, const unsigned int M, const unsigned int N, const unsigned int O);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
|
||||
// interp3_gpu.m - fast texture based GPU based interpolation method for 3D deformation
|
||||
//
|
||||
// RECOMPILE: mexcuda -output interp3_gpu_mex interp3_gpu_ker.cu interp3_gpu_mex.cpp
|
||||
//
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// %| |
|
||||
// %| Except where otherwise noted, this work is licensed under a |
|
||||
// %| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
// %| International (CC BY-NC-SA 4.0) license. |
|
||||
// %| |
|
||||
// %| Copyright (c) 2018 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
// %| |
|
||||
// %| Author: CXS group, PSI |
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// % You may use this code with the following provisions:
|
||||
// %
|
||||
// % If the code is fully or partially redistributed, or rewritten in another
|
||||
// % computing language this notice should be included in the redistribution.
|
||||
// %
|
||||
// % If this code, or subfunctions or parts of it, is used for research in a
|
||||
// % publication or if it is fully or partially rewritten for another
|
||||
// % computing language the authors and institution should be acknowledged
|
||||
// % in written form in the publication: “Data processing was carried out
|
||||
// % using the “cSAXS matlab package” developed by the CXS group,
|
||||
// % Paul Scherrer Institut, Switzerland.”
|
||||
// % Variations on the latter text can be incorporated upon discussion with
|
||||
// % the CXS group if needed to more specifically reflect the use of the package
|
||||
// % for the published work.
|
||||
// %
|
||||
// % A publication that focuses on describing features, or parameters, that
|
||||
// % are already existing in the code should be first discussed with the
|
||||
// % authors.
|
||||
// %
|
||||
// % This code and subroutines are part of a continuous development, they
|
||||
// % are provided “as they are” without guarantees or liability on part
|
||||
// % of PSI or the authors. It is the user responsibility to ensure its
|
||||
// % proper use and the correctness of the results.
|
||||
|
||||
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cuda_runtime_api.h>
|
||||
#include "interp3_gpu.hpp"
|
||||
#include <cuda.h>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
|
||||
#define MAX(x,y) (x>y?x:y);
|
||||
#define MIN(x,y) (x<y?x:y);
|
||||
#define ABS(x) (x>0?x:-x);
|
||||
#define INF (1023);
|
||||
|
||||
typedef const unsigned int cuint;
|
||||
typedef const int cint;
|
||||
|
||||
typedef texture<float, 3, cudaReadModeElementType> texture3D;
|
||||
|
||||
static texture3D ImgTexture, X_tex, Y_tex, Z_tex;
|
||||
|
||||
// splitting volume on smaller blocks to prevent GPU crashes
|
||||
static cuint g_blockX = 256;
|
||||
static cuint g_blockY = 256;
|
||||
static cuint g_blockZ = 256;
|
||||
|
||||
|
||||
cudaArray* allocateVolumeArray( cuint X, cuint Y, cuint Z)
|
||||
{
|
||||
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
|
||||
cudaArray* cuArray;
|
||||
cudaExtent extent;
|
||||
extent.width = X;
|
||||
extent.height = Y;
|
||||
extent.depth = Z;
|
||||
cudaError err = cudaMalloc3DArray(&cuArray, &channelDesc, extent);
|
||||
if (err != cudaSuccess) {
|
||||
mexPrintf ("Failed to allocate %dx%dx%d GPU array\n",X,Y,Z);
|
||||
return 0;
|
||||
}
|
||||
return cuArray;
|
||||
}
|
||||
|
||||
static bool bindVolumeDataTexture(const cudaArray* array, texture3D & Texture, bool normalized)
|
||||
{
|
||||
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
|
||||
Texture.addressMode[0] = cudaAddressModeClamp;
|
||||
Texture.addressMode[1] = cudaAddressModeClamp;
|
||||
Texture.addressMode[2] = cudaAddressModeClamp;
|
||||
Texture.filterMode = cudaFilterModeLinear; //cudaFilterModePoint
|
||||
Texture.normalized = normalized;
|
||||
|
||||
cudaError err = cudaBindTextureToArray(Texture, array, channelDesc);
|
||||
checkLastError("cudaBindTextureToArray ");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool transferVolumeToArray(const mxGPUArray * m_img, cudaArray *& array)
|
||||
{
|
||||
|
||||
mwSize const * dimensions = mxGPUGetDimensions(m_img);
|
||||
mwSize Ndim = mxGPUGetNumberOfDimensions(m_img);
|
||||
int M = (int)dimensions[0];
|
||||
int N = (int)dimensions[1];
|
||||
int O = Ndim > 2 ? (int)dimensions[2] : 1;
|
||||
|
||||
// get the values into float array
|
||||
const float * img =(const float *)mxGPUGetDataReadOnly(m_img);
|
||||
|
||||
array = allocateVolumeArray(M,N,O);
|
||||
if (array == 0)
|
||||
return false;
|
||||
|
||||
if (M * sizeof(float) > 2048) {
|
||||
mexPrintf("Volume is too large to be transfered to GPU array");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make volume array (no copying) */
|
||||
cudaPitchedPtr volume;
|
||||
volume.ptr = (float *)img;
|
||||
volume.pitch = M * sizeof(float);
|
||||
volume.xsize = M;
|
||||
volume.ysize = N;
|
||||
|
||||
cudaExtent extent;
|
||||
extent.width = M;
|
||||
extent.height = N;
|
||||
extent.depth = O;
|
||||
|
||||
cudaMemcpy3DParms p;
|
||||
cudaPos zp = { 0, 0, 0 };
|
||||
p.srcArray = 0;
|
||||
p.srcPos = zp;
|
||||
p.srcPtr = volume;
|
||||
p.dstArray = array;
|
||||
p.dstPtr.ptr = 0;
|
||||
p.dstPtr.pitch = 0;
|
||||
p.dstPtr.xsize = 0;
|
||||
p.dstPtr.ysize = 0;
|
||||
p.dstPos = zp;
|
||||
p.extent = extent;
|
||||
p.kind = cudaMemcpyDeviceToDevice;
|
||||
|
||||
cudaError err = cudaMemcpy3D(&p);
|
||||
|
||||
if (!checkLastError("transferVolumeToArray cudaMemcpy3D"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int checkLastError(char * msg)
|
||||
{
|
||||
cudaError_t cudaStatus = cudaGetLastError();
|
||||
if (cudaStatus != cudaSuccess) {
|
||||
char err[512];
|
||||
sprintf(err, "interp3 variation failed \n %s: %s. \n", msg, cudaGetErrorString(cudaStatus));
|
||||
mexErrMsgTxt(err);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
bool cudaTextForceKernelsCompletion()
|
||||
{
|
||||
cudaError_t returnedCudaError = cudaThreadSynchronize();
|
||||
if (returnedCudaError != cudaSuccess) {
|
||||
fprintf(stderr, "Failed to force completion of cuda kernels: %d: %s. \n ", returnedCudaError, cudaGetErrorString(returnedCudaError));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* TEXTURE TRILINEAR INTERPOLATION
|
||||
**/
|
||||
|
||||
|
||||
__global__ void kernel_interp3(float * p, cuint N, cuint M, cuint O,
|
||||
cuint Xstart, cuint Ystart, cuint Zstart) {
|
||||
|
||||
// Location in a 3D matrix
|
||||
mwSize m = Xstart+ blockIdx.x * blockDim.x + threadIdx.x;
|
||||
mwSize n = Ystart+ blockIdx.y * blockDim.y + threadIdx.y;
|
||||
mwSize o = Zstart+ blockIdx.z * blockDim.z + threadIdx.z;
|
||||
|
||||
if (m < M & n < N & o < O)
|
||||
{
|
||||
float xs, ys, zs; // shifted coordinates
|
||||
float mn, nn, on; // normalized coordinates
|
||||
mn = (float)(m)/M;
|
||||
nn = (float)(n)/N;
|
||||
on = (float)(o)/O;
|
||||
// mn = (m+0.5f);
|
||||
// nn = (n+0.5f);
|
||||
// on = (o+0.5f);
|
||||
// load deformed coordinates
|
||||
xs = m+0.5f - tex3D(X_tex,mn, nn, on);
|
||||
ys = n+0.5f - tex3D(Y_tex,mn, nn, on);
|
||||
zs = o+0.5f - tex3D(Z_tex,mn, nn, on);
|
||||
// get trilinear interplation
|
||||
bool outsiders = (xs > 0) & (ys > 0) & (zs > 0) &
|
||||
(xs < M) & (ys < N) & (zs < O);
|
||||
float p_val = (outsiders ? tex3D(ImgTexture,xs,ys,zs) : 0);
|
||||
// write the interpolation to the output
|
||||
p[(n)*N+(m)+(o)*M*N] = p_val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Host function called by MEX gateway.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
void interp3_init( float * p, const mxGPUArray * p0, const mxGPUArray *m_X, const mxGPUArray *m_Y, const mxGPUArray *m_Z, cuint M, cuint N, cuint O)
|
||||
{
|
||||
if (M*N*O*4 > 1024e6) {
|
||||
mexPrintf("Image size exceeded 1024MB, textures in interp3 will fail\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* move image to the texture array */
|
||||
cudaArray* cuArray, *cuArrayX, *cuArrayY, *cuArrayZ;
|
||||
checkLastError("after allocateVolumeArray");
|
||||
transferVolumeToArray(p0, cuArray);
|
||||
checkLastError("after transferVolumeToArray\n \n ");
|
||||
bindVolumeDataTexture(cuArray, ImgTexture, false);
|
||||
|
||||
/* move X deformation to the texture array */
|
||||
checkLastError("after allocateVolumeArray");
|
||||
transferVolumeToArray(m_X, cuArrayX);
|
||||
checkLastError("after transferVolumeToArray\n \n ");
|
||||
bindVolumeDataTexture(cuArrayX, X_tex, true);
|
||||
|
||||
/* move Y deformation to the texture array */
|
||||
checkLastError("after allocateVolumeArray");
|
||||
transferVolumeToArray(m_Y, cuArrayY);
|
||||
checkLastError("after transferVolumeToArray\n \n ");
|
||||
bindVolumeDataTexture(cuArrayY, Y_tex, true);
|
||||
|
||||
/* move Z deformation to the texture array */
|
||||
checkLastError("after allocateVolumeArray");
|
||||
transferVolumeToArray(m_Z, cuArrayZ);
|
||||
checkLastError("after transferVolumeToArray\n \n ");
|
||||
bindVolumeDataTexture(cuArrayZ, Z_tex, true);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// *************** 3-dim case ***************
|
||||
// Choose a reasonably sized number of threads in each dimension for the block.
|
||||
int const threadsPerBlockEachDim = 10; // MAX THREAD is 1024 ~ 10*10*10 for 3D
|
||||
dim3 const dimThread(threadsPerBlockEachDim, threadsPerBlockEachDim, threadsPerBlockEachDim);
|
||||
//mexPrintf("Thread %i %i %i \n ", dimThread.x, dimThread.y, dimThread.z);
|
||||
// Compute the thread block and grid sizes based on the board dimensions.
|
||||
int const blocksPerGrid_M = (g_blockX + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
int const blocksPerGrid_N = (g_blockY + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
int const blocksPerGrid_O = (g_blockZ + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
dim3 dimBlock(blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
|
||||
//mexPrintf("Block %i %i %i \n ", blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
|
||||
|
||||
std::list<cudaStream_t> streams;
|
||||
|
||||
for ( int blockXstart=0; blockXstart < M; blockXstart += g_blockX)
|
||||
for ( int blockYstart=0; blockYstart < N; blockYstart += g_blockY)
|
||||
for ( int blockZstart=0; blockZstart < O; blockZstart += g_blockZ)
|
||||
{
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
streams.push_back(stream);
|
||||
kernel_interp3<<<dimBlock, dimThread, 0, stream>>>
|
||||
(p,M,N,O, blockXstart,blockYstart,blockZstart);
|
||||
}
|
||||
|
||||
checkLastError("after kernel");
|
||||
cudaThreadSynchronize();
|
||||
for (std::list<cudaStream_t>::iterator iter = streams.begin(); iter != streams.end(); ++iter)
|
||||
cudaStreamDestroy(*iter);
|
||||
|
||||
streams.clear();
|
||||
|
||||
|
||||
|
||||
// clear memory , unbind textures
|
||||
|
||||
cudaTextForceKernelsCompletion();
|
||||
|
||||
cudaFreeArray(cuArray);
|
||||
cudaFreeArray(cuArrayX);
|
||||
cudaFreeArray(cuArrayY);
|
||||
cudaFreeArray(cuArrayZ);
|
||||
|
||||
checkLastError("after cudaFreeArray");
|
||||
cudaUnbindTexture(ImgTexture);
|
||||
cudaUnbindTexture(X_tex);
|
||||
cudaUnbindTexture(Y_tex);
|
||||
cudaUnbindTexture(Z_tex);
|
||||
checkLastError("cudaUnbindTexture");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
#include "interp3_gpu.hpp"
|
||||
|
||||
// interp3_gpu.m - fast texture based GPU based interpolation method for 3D deformation
|
||||
//
|
||||
// RECOMPILE: mexcuda -output interp3_gpu_mex interp3_gpu_ker.cu interp3_gpu_mex.cpp
|
||||
//
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// %| |
|
||||
// %| Except where otherwise noted, this work is licensed under a |
|
||||
// %| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
// %| International (CC BY-NC-SA 4.0) license. |
|
||||
// %| |
|
||||
// %| Copyright (c) 2018 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
// %| |
|
||||
// %| Author: CXS group, PSI |
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// % You may use this code with the following provisions:
|
||||
// %
|
||||
// % If the code is fully or partially redistributed, or rewritten in another
|
||||
// % computing language this notice should be included in the redistribution.
|
||||
// %
|
||||
// % If this code, or subfunctions or parts of it, is used for research in a
|
||||
// % publication or if it is fully or partially rewritten for another
|
||||
// % computing language the authors and institution should be acknowledged
|
||||
// % in written form in the publication: “Data processing was carried out
|
||||
// % using the “cSAXS matlab package” developed by the CXS group,
|
||||
// % Paul Scherrer Institut, Switzerland.”
|
||||
// % Variations on the latter text can be incorporated upon discussion with
|
||||
// % the CXS group if needed to more specifically reflect the use of the package
|
||||
// % for the published work.
|
||||
// %
|
||||
// % A publication that focuses on describing features, or parameters, that
|
||||
// % are already existing in the code should be first discussed with the
|
||||
// % authors.
|
||||
// %
|
||||
// % This code and subroutines are part of a continuous development, they
|
||||
// % are provided “as they are” without guarantees or liability on part
|
||||
// % of PSI or the authors. It is the user responsibility to ensure its
|
||||
// % proper use and the correctness of the results.
|
||||
|
||||
|
||||
/**
|
||||
* MEX gateway
|
||||
*/
|
||||
void mexFunction(int nlhs , mxArray *plhs[],
|
||||
int nrhs, mxArray const *prhs[])
|
||||
{
|
||||
char const * const errId = "parallel:gpu:interp3_gpu:InvalidInput";
|
||||
char const * const errMsg = "Invalid input to MEX file.";
|
||||
|
||||
// Initialize the MathWorks GPU API.
|
||||
mxInitGPU();
|
||||
|
||||
if (nrhs!=4) {
|
||||
mexPrintf("Wrong number of inputs\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
|
||||
|
||||
const mxGPUArray * m_Img_orig = mxGPUCreateFromMxArray(prhs[0]);
|
||||
if ((mxGPUGetClassID(m_Img_orig) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("wrong input m_Img_orig\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const float * p_Img_orig = (const float *)mxGPUGetDataReadOnly(m_Img_orig);
|
||||
|
||||
|
||||
const mxGPUArray * m_X = mxGPUCreateFromMxArray(prhs[1]);
|
||||
const mxGPUArray * m_Y = mxGPUCreateFromMxArray(prhs[2]);
|
||||
const mxGPUArray * m_Z = mxGPUCreateFromMxArray(prhs[3]);
|
||||
if ((mxGPUGetClassID(m_X) != mxSINGLE_CLASS) |
|
||||
(mxGPUGetClassID(m_Y) != mxSINGLE_CLASS) |
|
||||
(mxGPUGetClassID(m_Z) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("wrong input X,Y,Z\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
|
||||
mwSize const * dimensions = mxGPUGetDimensions(m_Img_orig);
|
||||
mwSize Ndim = mxGPUGetNumberOfDimensions(m_Img_orig);
|
||||
int M = (int)dimensions[0];
|
||||
int N = (int)dimensions[1];
|
||||
int O = Ndim > 2 ? (int)dimensions[2] : 1;
|
||||
|
||||
mxGPUArray * m_Img_out = mxGPUCreateGPUArray(Ndim,
|
||||
dimensions,
|
||||
mxSINGLE_CLASS,
|
||||
mxREAL,
|
||||
MX_GPU_INITIALIZE_VALUES);
|
||||
float * p_Img_out = (float *)mxGPUGetData(m_Img_out);
|
||||
|
||||
checkLastError("Before kernel run");
|
||||
|
||||
// mexcuda -output interp3_gpu_mex interp3_gpu_ker.cu interp3_gpu_mex.cpp
|
||||
|
||||
interp3_init( p_Img_out,m_Img_orig, m_X, m_Y, m_Z, M, N, O);
|
||||
|
||||
checkLastError("Before after run");
|
||||
|
||||
plhs[0] = mxGPUCreateMxArrayOnGPU(m_Img_out);
|
||||
|
||||
mxGPUDestroyGPUArray(m_Img_out);
|
||||
mxGPUDestroyGPUArray(m_Img_orig);
|
||||
mxGPUDestroyGPUArray(m_X);
|
||||
mxGPUDestroyGPUArray(m_Y);
|
||||
mxGPUDestroyGPUArray(m_Z);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
|
||||
#ifndef _MATLAB_OVERLOAD
|
||||
#define _MATLAB_OVERLOAD
|
||||
|
||||
#include "mex.h"
|
||||
|
||||
|
||||
// overload the GetData function for each of the possible data type + select the correct matlab get function
|
||||
inline void GetData(const mxArray *in, const mxComplexDouble *& out) { out = mxGetComplexDoubles(in); return; };
|
||||
inline void GetData(const mxArray *in, const mxComplexSingle *& out) { out = mxGetComplexSingles(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxComplexUint32 *& out) { out = mxGetComplexUint32s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxComplexUint16 *& out) { out = mxGetComplexUint16s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxComplexUint8 *& out) { out = mxGetComplexUint8s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxDouble *& out) { out = mxGetDoubles(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxSingle *& out) { out = mxGetSingles(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxUint32 *& out) { out = mxGetUint32s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxUint16 *& out) { out = mxGetUint16s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxUint8 *& out) { out = mxGetUint8s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexDouble *& out) { out = mxGetComplexDoubles(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexSingle *& out) { out = mxGetComplexSingles(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexUint32 *& out) { out = mxGetComplexUint32s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexUint16 *& out) { out = mxGetComplexUint16s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexUint8 *& out) { out = mxGetComplexUint8s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxDouble *& out) { out = mxGetDoubles(in); return;};
|
||||
inline void GetData(const mxArray *in, mxSingle *& out) { out = mxGetSingles(in); return;};
|
||||
inline void GetData(const mxArray *in, mxUint32 *& out) { out = mxGetUint32s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxUint16 *& out) { out = mxGetUint16s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxUint8 *& out) { out = mxGetUint8s(in); return;};
|
||||
|
||||
inline void AddData_atomic( mxDouble &out, const mxDouble &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxSingle &out, const mxSingle &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxUint32 &out, const mxUint32 &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxUint16 &out, const mxUint16 &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxUint8 &out, const mxUint8 &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxComplexDouble &out, const mxComplexDouble &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
inline void AddData_atomic( mxComplexSingle &out, const mxComplexSingle &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
inline void AddData_atomic( mxComplexUint32 &out, const mxComplexUint32 &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
inline void AddData_atomic( mxComplexUint16 &out, const mxComplexUint16 &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
inline void AddData_atomic( mxComplexUint8 &out, const mxComplexUint8 &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
|
||||
inline void AddData( mxDouble &out, const mxDouble &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxSingle &out, const mxSingle &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxUint32 &out, const mxUint32 &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxUint16 &out, const mxUint16 &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxUint8 &out, const mxUint8 &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxComplexDouble &out, const mxComplexDouble &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
inline void AddData( mxComplexSingle &out, const mxComplexSingle &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
inline void AddData( mxComplexUint32 &out, const mxComplexUint32 &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
inline void AddData( mxComplexUint16 &out, const mxComplexUint16 &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
inline void AddData( mxComplexUint8 &out, const mxComplexUint8 &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
|
||||
inline void SetData( mxDouble &out, const mxDouble &in) { out = in; };
|
||||
inline void SetData( mxSingle &out, const mxSingle &in) { out = in; };
|
||||
inline void SetData( mxUint32 &out, const mxUint32 &in) { out = in; };
|
||||
inline void SetData( mxUint16 &out, const mxUint16 &in) { out = in; };
|
||||
inline void SetData( mxUint8 &out, const mxUint8 &in) { out = in; };
|
||||
inline void SetData( mxComplexDouble &out, const mxComplexDouble &in) { out.real = in.real; out.imag = in.imag; };
|
||||
inline void SetData( mxComplexSingle &out, const mxComplexSingle &in) { out.real = in.real; out.imag = in.imag; };
|
||||
inline void SetData( mxComplexUint32 &out, const mxComplexUint32 &in) { out.real = in.real; out.imag = in.imag; };
|
||||
inline void SetData( mxComplexUint16 &out, const mxComplexUint16 &in) { out.real = in.real; out.imag = in.imag; };
|
||||
inline void SetData( mxComplexUint8 &out, const mxComplexUint8 &in) { out.real = in.real; out.imag = in.imag; };
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user