mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-18 01:59:11 +09:00
initial commit
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
|
||||
Academic License Agreement
|
||||
|
||||
Source Code
|
||||
|
||||
Introduction
|
||||
• This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
|
||||
will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
|
||||
ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
|
||||
|
||||
Terms and Conditions of the LICENSE
|
||||
1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
|
||||
hereinafter set out and until termination of this license as set forth below.
|
||||
2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
|
||||
or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
|
||||
LICENSEE’s responsibility to ensure its proper use and the correctness of the results.”
|
||||
3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
||||
A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
|
||||
OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
|
||||
4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
|
||||
"IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
|
||||
license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
|
||||
profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
|
||||
in the commercial use, application or exploitation of works similar to the PROGRAM.
|
||||
5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
|
||||
another computing language:
|
||||
"Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
|
||||
Scherrer Institut, Switzerland."
|
||||
|
||||
Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
|
||||
P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379–382 (2008).
|
||||
(doi: 10.1126/science.1158573),
|
||||
for mixed coherent modes:
|
||||
P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 68–71 (2013). (doi: 10.1038/nature11806),
|
||||
for LSQ-ML method
|
||||
M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
|
||||
for OPRP method
|
||||
M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
|
||||
and/or for multislice:
|
||||
E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 29089–29108 (2016).
|
||||
6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
|
||||
names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
|
||||
7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
|
||||
agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
|
||||
make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
|
||||
© All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
|
||||
8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
|
||||
9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
|
||||
to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
|
||||
in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
|
||||
in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
|
||||
10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
|
||||
the courts of Zürich, Switzerland.
|
||||
|
||||
|
||||
*
|
||||
Compilation from Matlab:
|
||||
maybe a tiny bit faster code is generated by
|
||||
mex -O COPTIMFLAGS='-O2' LDOPTIMFLAGS='-O2' CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp" get_views_cpu_mex.cpp
|
||||
|
||||
Usage from Matlab:
|
||||
get_views_cpu_mex(object,obj_proj,positions, ind_ok);
|
||||
|
||||
This code in matlab:
|
||||
asize = size(probe);
|
||||
for i=ind_ok
|
||||
Indy = positions(i,1) + (1:asize(1));
|
||||
Indx = positions(i,2) + (1:asize(2));
|
||||
ob(Indy,Indx) = ob(Indy,Indx) + probe;
|
||||
end
|
||||
*/
|
||||
|
||||
#include "mex.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <omp.h>
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check for proper number of arguments. */
|
||||
if (nrhs != 4)
|
||||
mexErrMsgTxt("Four input arguments required: get_views_cpu_mex(object,obj_proj,positions,ind_ok)");
|
||||
else if (nlhs != 0)
|
||||
mexErrMsgTxt("No output argument has to be specified.");
|
||||
|
||||
/* Input must be of type single. */
|
||||
for (i=0; i < 2; i++) {
|
||||
if (mxIsSingle(prhs[i]) != 1){
|
||||
printf(" Input %d is not single\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
/* Input must be of type int32. */
|
||||
for (i=2; i<nrhs; i++){
|
||||
if (mxIsInt32(prhs[i]) != 1){
|
||||
printf("Input %d is not integer\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
|
||||
/* It cannot be one-dimensional */
|
||||
if(mxGetNumberOfDimensions(prhs[0]) < 2) {
|
||||
printf("The 1st input argument must have at least two dimensions.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
|
||||
}
|
||||
/* It cannot be more than 3-dimensional */
|
||||
if(mxGetNumberOfDimensions(prhs[0]) > 3) {
|
||||
printf("The 1st input argument must have at most three dimensions.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
|
||||
}
|
||||
/* Check that arrays are complex */
|
||||
if(mxIsComplex(prhs[0]) != 1) {
|
||||
printf("object input argument must be complex-valued.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
|
||||
}
|
||||
if(mxIsComplex(prhs[1]) != 1) {
|
||||
printf("probe input argument must be complex-valued.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
|
||||
}
|
||||
|
||||
float *object_r, *object_i, *projection_r,*projection_i;
|
||||
const int *positions;
|
||||
positions = (int*)mxGetData(prhs[2]);
|
||||
object_r = (float*)mxGetData(prhs[0]);
|
||||
projection_r = (float*)mxGetData(prhs[1]);
|
||||
|
||||
/* get pointers to input data */
|
||||
object_i = (float*)mxGetImagData(prhs[0]);
|
||||
projection_i = (float*)mxGetImagData(prhs[1]);
|
||||
|
||||
|
||||
/* Get dimension of probe and object */
|
||||
const mwSize Ndims = mxGetNumberOfDimensions(prhs[1]);
|
||||
const mwSize * dims = mxGetDimensions(prhs[1]);
|
||||
const mwSize No_y = mxGetM(prhs[0]);
|
||||
const mwSize No_x = mxGetN(prhs[0]);
|
||||
const mwSize Np_y = dims[0];
|
||||
const mwSize Np_x = dims[1];
|
||||
const mwSize Npos = mxGetM(prhs[2]);
|
||||
|
||||
if((Npos > dims[2])) {
|
||||
printf("wrong size of update / positions %i", Ndims);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
|
||||
}
|
||||
|
||||
mwSize id_small, id_large, pos, col, row;
|
||||
#pragma omp parallel for private(pos,col, row, id_small, id_large)
|
||||
for (pos=0;pos<Npos;pos++){
|
||||
for (col=0;col<Np_x;col++) {
|
||||
for (row=0;row<Np_y;row++) {
|
||||
id_small = row + col*Np_y + Np_y*Np_x*pos;
|
||||
id_large = row + positions[pos] + (col+positions[pos+Npos])*No_y;
|
||||
projection_r[id_small] = object_r[id_large];
|
||||
projection_i[id_small] = object_i[id_large];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
Get complex views from complex object
|
||||
mexcuda -output +engines/+GPU/+shared/private/get_views_gpu_mex +engines/+GPU/+shared/private/get_views_gpu_mex.cu
|
||||
*/
|
||||
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
typedef const unsigned int cuint;
|
||||
typedef const uint16_T cuint16;
|
||||
|
||||
// unfortunatelly ~10800 is the maximum of const memory
|
||||
const unsigned int MAX_IND_READ = 10800;
|
||||
__constant__ uint16_T gC_ind_read[MAX_IND_READ];
|
||||
__constant__ uint16_T gC_pos_X[MAX_IND_READ];
|
||||
__constant__ uint16_T gC_pos_Y[MAX_IND_READ];
|
||||
|
||||
|
||||
#define MAX(x,y) (x>y?x:y);
|
||||
#define MIN(x,y) (x<y?x:y);
|
||||
#define ABS(x) (x>0?x:-x);
|
||||
|
||||
|
||||
int checkLastError(char * msg)
|
||||
{
|
||||
cudaError_t cudaStatus = cudaGetLastError();
|
||||
if (cudaStatus != cudaSuccess) {
|
||||
char err[512];
|
||||
sprintf(err, "getprojection failed \n %s: %s. \n", msg, cudaGetErrorString(cudaStatus));
|
||||
mexPrintf(err);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Device code
|
||||
*/
|
||||
/*********** fast const memory based version ***************/
|
||||
|
||||
__global__ void readFromArray_c_fast(float2 * sarray, const float2 * larray,
|
||||
cuint Np_px,cuint Np_py, cuint Np_pz,cuint Np_ox, cuint Np_oy,
|
||||
cuint Npos) {
|
||||
// Location in a 3D matrix
|
||||
int idx= blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int idy= blockIdx.y * blockDim.y + threadIdx.y;
|
||||
int id = blockIdx.z * blockDim.z + threadIdx.z;
|
||||
|
||||
if ( idx < Np_px & idy < Np_py & id < Npos)
|
||||
{
|
||||
int idz = gC_ind_read[id]-1; // go only through some of the indices
|
||||
int id_large = gC_pos_X[idz]+idx + Np_ox*(gC_pos_Y[idz]+idy);
|
||||
int id_small = idx + Np_px*idy + Np_px*Np_py*idz ;
|
||||
sarray[ id_small ].x = larray[ id_large ].x ;
|
||||
sarray[ id_small ].y = larray[ id_large ].y ;
|
||||
}
|
||||
}
|
||||
/*********** global memory based version ***************/
|
||||
|
||||
__global__ void readFromArray_c(float2 * sarray, const float2 * larray, cuint16* ind_read, cuint16* pos_X, cuint16* posY,
|
||||
cuint Np_px,cuint Np_py, cuint Np_pz,cuint Np_ox, cuint Np_oy,
|
||||
cuint Npos) {
|
||||
// Location in a 3D matrix
|
||||
int idx= blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int idy= blockIdx.y * blockDim.y + threadIdx.y;
|
||||
int id = blockIdx.z * blockDim.z + threadIdx.z;
|
||||
|
||||
if ( idx < Np_px & idy < Np_py & id < Npos)
|
||||
{
|
||||
int idz = ind_read[id]-1; // go only through some of the indices
|
||||
int id_large = pos_X[idz]+idx + Np_ox*(posY[idz]+idy);
|
||||
int id_small = idx + Np_px*idy + Np_px*Np_py*idz ;
|
||||
sarray[ id_small ].x = larray[ id_large ].x ;
|
||||
sarray[ id_small ].y = larray[ id_large ].y ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
int i ;
|
||||
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
|
||||
char const * const errMsg = "Invalid input to MEX file.";
|
||||
|
||||
/* Initialize the MathWorks GPU API. */
|
||||
//mxInitGPU();
|
||||
|
||||
/* Check for proper number of arguments. */
|
||||
if (nrhs != 5)
|
||||
mexErrMsgTxt("Five input arguments required");
|
||||
|
||||
|
||||
for (i=0; i < 2; i++) {
|
||||
if ( !mxIsGPUArray(prhs[i]) && !mxIsCell(prhs[i]) ){
|
||||
printf("Input %d is not GPU array / cell \n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// load positions
|
||||
|
||||
|
||||
const mxGPUArray * m_positions_x = mxGPUCreateFromMxArray(prhs[2]);
|
||||
if ((mxGPUGetClassID(m_positions_x) != mxUINT16_CLASS)) {
|
||||
mexPrintf("m_positions_x\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const cuint16 * p_positions_x = (cuint16 *)mxGPUGetDataReadOnly(m_positions_x);
|
||||
|
||||
const mxGPUArray * m_positions_y = mxGPUCreateFromMxArray(prhs[3]);
|
||||
if ((mxGPUGetClassID(m_positions_y) != mxUINT16_CLASS)) {
|
||||
mexPrintf("m_positions_y\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const cuint16 * p_positions_y = (cuint16 *)mxGPUGetDataReadOnly(m_positions_y);
|
||||
|
||||
|
||||
/**** copy of the array is the slowest operation *****/
|
||||
// Now it is writting directly into the input field !!!
|
||||
//mxGPUArray * m_obj_proj = mxGPUCopyFromMxArray(prhs[0]);
|
||||
mxGPUArray * m_obj_proj = const_cast<mxGPUArray*>(mxGPUCreateFromMxArray(prhs[0])); //
|
||||
if ((mxGPUGetClassID(m_obj_proj) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("m_obj_proj\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
if (mxGPUGetComplexity(m_obj_proj) != mxCOMPLEX) {
|
||||
mexPrintf("m_obj_proj is not complex \n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
float2 * p_obj_proj = (float2 *)mxGPUGetData(m_obj_proj);
|
||||
|
||||
|
||||
if (!mxIsCell(prhs[1]) || !mxIsCell(prhs[4]))
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Object and indices has to be in cell/cells !! ");
|
||||
if (mxGetNumberOfElements(prhs[1]) != mxGetNumberOfElements(prhs[4]))
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Number of objects != number of indices ");
|
||||
|
||||
|
||||
/* Get dimension of probe and object */
|
||||
const unsigned int Ndims = (unsigned int)mxGPUGetNumberOfDimensions(m_obj_proj);
|
||||
|
||||
|
||||
cuint Ncells = mxGetNumberOfElements(prhs[1]);
|
||||
const unsigned int Np_pp = mxGPUGetNumberOfElements(m_positions_x);
|
||||
|
||||
|
||||
if (Np_pp < MAX_IND_READ) {
|
||||
cudaMemcpyToSymbol(gC_pos_X, p_positions_x, Np_pp*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
|
||||
cudaMemcpyToSymbol(gC_pos_Y, p_positions_y, Np_pp*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
|
||||
checkLastError("after cudaMemcpyToSymbol pos");
|
||||
}
|
||||
|
||||
for (int l=0; l<Ncells; l++)
|
||||
{
|
||||
// read the cell content
|
||||
mxArray * mx_object = mxGetCell(prhs[1],l);
|
||||
mxArray * mx_ind = mxGetCell(prhs[4],l);
|
||||
int N_ok = mxGetNumberOfElements(mx_ind);
|
||||
if(N_ok == 0)
|
||||
continue;
|
||||
|
||||
const mxGPUArray * m_object = mxGPUCreateFromMxArray(mx_object);
|
||||
if ((mxGPUGetClassID(m_object) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("m_object\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
if (mxGPUGetComplexity(m_object) != mxCOMPLEX) {
|
||||
mexPrintf("m_object is not complex \n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const float2 * p_object = (float2 *)mxGPUGetDataReadOnly(m_object);
|
||||
|
||||
|
||||
const mxGPUArray * m_ind_ok = mxGPUCreateFromMxArray(mx_ind);
|
||||
if ((mxGPUGetClassID(m_ind_ok) != mxUINT16_CLASS)) {
|
||||
mexPrintf("m_ind_ok\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const cuint16 * p_ind_ok = (cuint16 *)mxGPUGetDataReadOnly(m_ind_ok);
|
||||
|
||||
const mwSize * Np_o = mxGPUGetDimensions(m_object);
|
||||
const mwSize * Np_p = mxGPUGetDimensions(m_obj_proj);
|
||||
const unsigned int Npos = mxGPUGetNumberOfElements(m_ind_ok);
|
||||
|
||||
|
||||
|
||||
// mexPrintf("Ndims %i Np_o %i %i Np_p %i %i %i Npos %i \n " ,Ndims,Np_o[0],Np_o[1],Np_p[0],Np_p[1],Np_p[2],Npos);
|
||||
|
||||
|
||||
|
||||
|
||||
if (Ndims == 3 && Npos > Np_p[2]) {
|
||||
printf("wrong size of update / positions %i", Ndims);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Choose a reasonably sized number of threads in each dimension for the block.
|
||||
int const threadsPerBlockEachDim = 32;
|
||||
// Compute the thread block and grid sizes based on the board dimensions.
|
||||
int const blocksPerGrid_M = (Np_p[0] + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
int const blocksPerGrid_N = (Np_p[1] + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
int const blocksPerGrid_O = Npos;
|
||||
|
||||
// mexPrintf("Threads %i %i %i \n ", blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
|
||||
|
||||
dim3 const dimBlock(blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
|
||||
dim3 const dimThread(threadsPerBlockEachDim, threadsPerBlockEachDim, 1);
|
||||
|
||||
|
||||
checkLastError("after dimThread");
|
||||
|
||||
//mexPrintf("Blocks %i %i %i \n ", dimThread.x, dimThread.y, dimThread.z);
|
||||
|
||||
if (Np_pp > MAX_IND_READ) {
|
||||
//mexPrintf( "More than %i positions may be slow \n", MAX_IND_READ);
|
||||
} else {
|
||||
cudaMemcpyToSymbol(gC_ind_read, p_ind_ok, Npos*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
|
||||
checkLastError("after cudaMemcpyToSymbol pos");
|
||||
}
|
||||
|
||||
checkLastError("after cudaMemcpyToSymbol");
|
||||
|
||||
|
||||
//============= run the kernel ======================
|
||||
if (Npos < MAX_IND_READ)
|
||||
readFromArray_c_fast<<<dimBlock, dimThread>>>(p_obj_proj,p_object, Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos);
|
||||
else
|
||||
readFromArray_c<<<dimBlock, dimThread>>>(p_obj_proj,p_object,p_ind_ok, p_positions_x,p_positions_y,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos);
|
||||
|
||||
|
||||
checkLastError("after kernel");
|
||||
|
||||
|
||||
mxGPUDestroyGPUArray(m_object);
|
||||
mxGPUDestroyGPUArray(m_ind_ok);
|
||||
|
||||
|
||||
}
|
||||
|
||||
cudaThreadSynchronize();
|
||||
|
||||
|
||||
// plhs[0] = mxGPUCreateMxArrayOnGPU(m_obj_proj);
|
||||
mxGPUDestroyGPUArray(m_obj_proj);
|
||||
mxGPUDestroyGPUArray(m_positions_x);
|
||||
mxGPUDestroyGPUArray(m_positions_y);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
*
|
||||
*Academic License Agreement
|
||||
|
||||
Source Code
|
||||
|
||||
Introduction
|
||||
• This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
|
||||
will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
|
||||
ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
|
||||
|
||||
Terms and Conditions of the LICENSE
|
||||
1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
|
||||
hereinafter set out and until termination of this license as set forth below.
|
||||
2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
|
||||
or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
|
||||
LICENSEE’s responsibility to ensure its proper use and the correctness of the results.”
|
||||
3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
||||
A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
|
||||
OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
|
||||
4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
|
||||
"IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
|
||||
license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
|
||||
profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
|
||||
in the commercial use, application or exploitation of works similar to the PROGRAM.
|
||||
5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
|
||||
another computing language:
|
||||
"Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
|
||||
Scherrer Institut, Switzerland."
|
||||
|
||||
Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
|
||||
P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379–382 (2008).
|
||||
(doi: 10.1126/science.1158573),
|
||||
for mixed coherent modes:
|
||||
P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 68–71 (2013). (doi: 10.1038/nature11806),
|
||||
for LSQ-ML method
|
||||
M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
|
||||
for OPRP method
|
||||
M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
|
||||
and/or for multislice:
|
||||
E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 29089–29108 (2016).
|
||||
6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
|
||||
names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
|
||||
7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
|
||||
agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
|
||||
make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
|
||||
© All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
|
||||
8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
|
||||
9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
|
||||
to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
|
||||
in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
|
||||
in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
|
||||
10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
|
||||
the courts of Zürich, Switzerland.
|
||||
|
||||
|
||||
*
|
||||
*
|
||||
Compilation from Matlab:
|
||||
maybe a tiny bit faster code is generated by
|
||||
mex -O COPTIMFLAGS='-O2' LDOPTIMFLAGS='-O2' set_views_cpu_mex.c
|
||||
|
||||
Usage from Matlab:
|
||||
set_views_cpu_mex(probe,object,positions, Npos);
|
||||
|
||||
This code in matlab:
|
||||
asize = size(probe);
|
||||
for i=1:Npos
|
||||
Indy = positions(i,1) + (1:asize(1));
|
||||
Indx = positions(i,2) + (1:asize(2));
|
||||
ob(Indy,Indx) = ob(Indy,Indx) + probe;
|
||||
end
|
||||
*/
|
||||
|
||||
#include "mex.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <omp.h>
|
||||
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check for proper number of arguments. */
|
||||
if (nrhs != 4)
|
||||
mexErrMsgTxt("Four input arguments required: set_views_cpu_mex(probe,object,positions,Npos)");
|
||||
else if (nlhs != 0)
|
||||
mexErrMsgTxt("No output argument has to be specified.");
|
||||
|
||||
/* Input must be of type single. */
|
||||
for (i=0; i < 2; i++) {
|
||||
if (mxIsSingle(prhs[i]) != 1){
|
||||
printf("Input %d is not single\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
/* Input must be of type int32. */
|
||||
for (i=2; i<nrhs; i++){
|
||||
if (mxIsInt32(prhs[i]) != 1){
|
||||
printf("Input %d is not integer\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
|
||||
/* It cannot be one-dimensional */
|
||||
if(mxGetNumberOfDimensions(prhs[0]) < 2) {
|
||||
printf("The 1st input argument must have at least two dimensions.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
|
||||
}
|
||||
/* It cannot be more than 3-dimensional */
|
||||
if(mxGetNumberOfDimensions(prhs[0]) > 3) {
|
||||
printf("The 1st input argument must have at most three dimensions.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
|
||||
}
|
||||
// /* Check that arrays are complex */
|
||||
// if(mxIsComplex(prhs[0]) != 1) {
|
||||
// printf("object input argument must be complex-valued.");
|
||||
// mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
|
||||
// }
|
||||
// if(mxIsComplex(prhs[1]) != 1) {
|
||||
// printf("probe input argument must be complex-valued.");
|
||||
// mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
|
||||
// }
|
||||
|
||||
float *object_r, *object_i, *probe_r,*probe_i;
|
||||
const int *positions, *ind_ok;
|
||||
bool cprobe, cobject;
|
||||
|
||||
cobject = mxIsComplex(prhs[0]);
|
||||
cprobe = mxIsComplex(prhs[1]);
|
||||
if( cobject != cobject)
|
||||
{
|
||||
printf("probe/object input argument must be complex/real-valued.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Expected both complex / real arrays");
|
||||
}
|
||||
|
||||
ind_ok = (int*)mxGetData(prhs[3]);
|
||||
positions = (int*)mxGetData(prhs[2]);
|
||||
object_r = (float*)mxGetData(prhs[0]);
|
||||
probe_r = (float*)mxGetData(prhs[1]);
|
||||
if(cprobe)
|
||||
{
|
||||
/* get pointers to input data */
|
||||
object_i = (float*)mxGetImagData(prhs[0]);
|
||||
probe_i = (float*)mxGetImagData(prhs[1]);
|
||||
}
|
||||
|
||||
|
||||
/* Get dimension of probe and object */
|
||||
const mwSize Ndims = mxGetNumberOfDimensions(prhs[1]);
|
||||
const mwSize * dims = mxGetDimensions(prhs[1]);
|
||||
const mwSize No_y = mxGetM(prhs[0]);
|
||||
const mwSize No_x = mxGetN(prhs[0]);
|
||||
const mwSize Np_y = dims[0];
|
||||
const mwSize Np_x = dims[1];
|
||||
const mwSize Npos = mxGetM(prhs[2]);
|
||||
|
||||
if((mxGetM(prhs[2]) != dims[2]) && (Ndims == 3)) {
|
||||
printf("wrong size of update / positions %i", Ndims);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
|
||||
}
|
||||
|
||||
mwSize id_small, id_large, pos, col, row, o, p;
|
||||
bool flat_probe = Ndims == 2;
|
||||
|
||||
|
||||
#pragma omp parallel for private(p,pos, col, row, id_small, id_large)
|
||||
for (p=0;p<Npos;p++){
|
||||
pos = ind_ok[p]-1;
|
||||
for (col=0;col<Np_x;col++) {
|
||||
for (row=0;row<Np_y;row++) {
|
||||
if(flat_probe)
|
||||
id_small = row + col*Np_y;
|
||||
else
|
||||
id_small = row + col*Np_y + Np_y*Np_x*pos;
|
||||
|
||||
id_large = row + positions[pos] + (col+positions[pos+Npos])*No_y;
|
||||
|
||||
#pragma omp atomic
|
||||
object_r[id_large] += probe_r[id_small];
|
||||
if(cprobe)
|
||||
#pragma omp atomic
|
||||
object_i[id_large] += probe_i[id_small];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
*
|
||||
*Academic License Agreement
|
||||
|
||||
Source Code
|
||||
|
||||
Introduction
|
||||
• This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
|
||||
will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
|
||||
ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
|
||||
|
||||
Terms and Conditions of the LICENSE
|
||||
1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
|
||||
hereinafter set out and until termination of this license as set forth below.
|
||||
2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
|
||||
or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
|
||||
LICENSEE’s responsibility to ensure its proper use and the correctness of the results.”
|
||||
3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
||||
A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
|
||||
OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
|
||||
4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
|
||||
"IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
|
||||
license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
|
||||
profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
|
||||
in the commercial use, application or exploitation of works similar to the PROGRAM.
|
||||
5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
|
||||
another computing language:
|
||||
"Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
|
||||
Scherrer Institut, Switzerland."
|
||||
|
||||
Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
|
||||
P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379–382 (2008).
|
||||
(doi: 10.1126/science.1158573),
|
||||
for mixed coherent modes:
|
||||
P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 68–71 (2013). (doi: 10.1038/nature11806),
|
||||
for LSQ-ML method
|
||||
M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
|
||||
for OPRP method
|
||||
M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
|
||||
and/or for multislice:
|
||||
E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 29089–29108 (2016).
|
||||
6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
|
||||
names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
|
||||
7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
|
||||
agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
|
||||
make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
|
||||
© All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
|
||||
8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
|
||||
9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
|
||||
to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
|
||||
in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
|
||||
in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
|
||||
10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
|
||||
the courts of Zürich, Switzerland.
|
||||
|
||||
|
||||
*
|
||||
*
|
||||
Compilation from Matlab:
|
||||
maybe a tiny bit faster code is generated by
|
||||
mex -O COPTIMFLAGS='-O2' LDOPTIMFLAGS='-O2' set_views_cpu_mex_rc.cpp
|
||||
|
||||
Usage from Matlab:
|
||||
set_views_cpu_mex(probe,object,positions, Npos);
|
||||
|
||||
This code in matlab:
|
||||
asize = size(probe);
|
||||
for i=1:Npos
|
||||
Indy = positions(i,1) + (1:asize(1));
|
||||
Indx = positions(i,2) + (1:asize(2));
|
||||
ob(Indy,Indx) = ob(Indy,Indx) + probe;
|
||||
end
|
||||
*/
|
||||
|
||||
#include "mex.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <omp.h>
|
||||
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check for proper number of arguments. */
|
||||
if (nrhs != 6)
|
||||
mexErrMsgTxt("Six input arguments required: set_views_cpu_mex_rc(object,obj_upd, illum, illum_upd, positions,ind_ok)");
|
||||
else if (nlhs != 0)
|
||||
mexErrMsgTxt("No output argument has to be specified.");
|
||||
|
||||
/* Input must be of type single. */
|
||||
for (i=0; i < 4; i++) {
|
||||
if (mxIsSingle(prhs[i]) != 1){
|
||||
printf("Input %d is not single\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
/* Input must be of type int32. */
|
||||
for (i=4; i<nrhs; i++){
|
||||
if (mxIsInt32(prhs[i]) != 1){
|
||||
printf("Input %d is not integer\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that arrays are complex */
|
||||
if(mxIsComplex(prhs[0]) != 1) {
|
||||
printf("first input argument must be complex-valued.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
|
||||
}
|
||||
if(mxIsComplex(prhs[1]) == 1) {
|
||||
printf("second input argument must be real-valued.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Expected real arrays");
|
||||
}
|
||||
if(mxIsComplex(prhs[2]) != 1) {
|
||||
printf("third input argument must be complex-valued.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
|
||||
}
|
||||
if(mxIsComplex(prhs[3]) == 1) {
|
||||
printf("fourth input argument must be real-valued.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Expected real arrays");
|
||||
}
|
||||
|
||||
|
||||
|
||||
float *object_r, *object_i, *probe_r,*probe_i, *illum_r, *illum_upd;
|
||||
const int *positions, *ind_ok;
|
||||
bool cprobe, cobject;
|
||||
|
||||
positions = (int*)mxGetData(prhs[4]);
|
||||
ind_ok = (int*)mxGetData(prhs[5]);
|
||||
object_r = (float*)mxGetData(prhs[0]);
|
||||
object_i = (float*)mxGetImagData(prhs[0]);
|
||||
illum_r = (float*)mxGetData(prhs[1]);
|
||||
probe_r = (float*)mxGetData(prhs[2]);
|
||||
probe_i = (float*)mxGetImagData(prhs[2]);
|
||||
illum_upd = (float*)mxGetData(prhs[3]);
|
||||
|
||||
|
||||
|
||||
/* Get dimension of probe and object */
|
||||
const mwSize Ndims = mxGetNumberOfDimensions(prhs[2]);
|
||||
const mwSize * dims = mxGetDimensions(prhs[2]);
|
||||
const mwSize No_y = mxGetM(prhs[0]);
|
||||
const mwSize No_x = mxGetN(prhs[0]);
|
||||
const mwSize Np_y = dims[0];
|
||||
const mwSize Np_x = dims[1];
|
||||
const mwSize Npos = mxGetNumberOfElements(prhs[5]);
|
||||
|
||||
|
||||
if(mxGetM(prhs[4]) != dims[2]) {
|
||||
printf("wrong size of update / positions %i", Ndims);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
|
||||
}
|
||||
|
||||
// mexPrintf("O %i %i P %i %i N %i \n ", No_y, No_x, Np_y, Np_x, Npos);
|
||||
|
||||
mwSize id_small, id_small_3D, id_large, pos, col, row, p;
|
||||
|
||||
#pragma omp parallel for private(p,pos, col, row, id_small,id_small_3D, id_large)
|
||||
for (p=0;p<Npos;p++){
|
||||
pos = ind_ok[p]-1;
|
||||
for (col=0;col<Np_x;col++) {
|
||||
for (row=0;row<Np_y;row++) {
|
||||
id_small = row + col*Np_y;
|
||||
id_small_3D = id_small + Np_y*Np_x*pos;
|
||||
id_large = row + positions[pos] + (col+positions[pos+Npos])*No_y;
|
||||
#pragma omp atomic
|
||||
object_r[id_large] += probe_r[id_small_3D];
|
||||
#pragma omp atomic
|
||||
object_i[id_large] += probe_i[id_small_3D];
|
||||
#pragma omp atomic
|
||||
illum_r[id_large] += illum_upd[id_small];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
Set complex views to complex object
|
||||
mexcuda -output +engines/+GPU/+shared/private/set_views_gpu_mex +engines/+GPU/+shared/private/set_views_gpu_mex.cu
|
||||
*/
|
||||
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef const unsigned int cuint;
|
||||
typedef const uint16_T cuint16;
|
||||
|
||||
// unfortunatelly ~10800 is the maximum of const memory
|
||||
const unsigned int MAX_IND_READ = 10800;
|
||||
static const unsigned MAX_IND_READ_DEV = MAX_IND_READ;
|
||||
__constant__ uint16_T gC_ind_read[MAX_IND_READ_DEV];
|
||||
__constant__ uint16_T gC_pos_X[MAX_IND_READ_DEV];
|
||||
__constant__ uint16_T gC_pos_Y[MAX_IND_READ_DEV];
|
||||
|
||||
|
||||
int checkLastError(char * msg)
|
||||
{
|
||||
cudaError_t cudaStatus = cudaGetLastError();
|
||||
if (cudaStatus != cudaSuccess) {
|
||||
char err[512];
|
||||
sprintf(err, "setprojection failed \n %s: %s. \n", msg, cudaGetErrorString(cudaStatus));
|
||||
mexPrintf(err);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Device code
|
||||
*/
|
||||
|
||||
/*********** reduction of object projection array to single object ***************/
|
||||
template <bool useGlobal>
|
||||
__global__ void addToArray_r( float const * sarray, float * larray, cuint16* ind_read, cuint16* pos_X, cuint16* posY,
|
||||
cuint Np_px,cuint Np_py, cuint Np_pz,cuint Np_ox, cuint Np_oy,
|
||||
cuint Npos, const bool isFlat) {
|
||||
// Location in a 3D matrix
|
||||
int idx= blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int idy= blockIdx.y * blockDim.y + threadIdx.y;
|
||||
if ( idx < Np_px & idy < Np_py ) {
|
||||
int idz, id_large;
|
||||
float sarray_val;
|
||||
for(int id = 0; id < Npos; id++)
|
||||
{
|
||||
if (useGlobal) {
|
||||
// fast const memory based version
|
||||
idz = gC_ind_read[id]-1; // go only through some of the indices
|
||||
id_large = gC_pos_X[idz]+idx + Np_ox*(gC_pos_Y[idz]+idy);
|
||||
} else {
|
||||
// slower global memory based version
|
||||
idz = ind_read[id]-1; // go only through some of the indices
|
||||
id_large = pos_X[idz]+idx + Np_ox*(posY[idz]+idy);
|
||||
}
|
||||
int id_small = idx + Np_px*idy ;
|
||||
if (!isFlat)
|
||||
id_small = id_small + Np_px*Np_py*idz ;
|
||||
|
||||
// prevent extra memory load
|
||||
sarray_val = (isFlat && (idz > 0)) ? sarray_val: sarray[ id_small ];
|
||||
|
||||
//larray[id_large] += sarray_val;
|
||||
//__syncthreads();
|
||||
|
||||
// slowest step, without atomicAdd it misses some values
|
||||
atomicAdd(&larray[id_large] ,sarray_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <bool useGlobal>
|
||||
__global__ void addToArray_c( float2 const * sarray, float2 * larray, cuint16* ind_read, cuint16* pos_X, cuint16* posY,
|
||||
cuint Np_px,cuint Np_py, cuint Np_pz,cuint Np_ox, cuint Np_oy,
|
||||
cuint Npos, const bool isFlat) {
|
||||
// Location in a 3D matrix
|
||||
int idx= blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int idy= blockIdx.y * blockDim.y + threadIdx.y;
|
||||
if ( idx < Np_px & idy < Np_py ) {
|
||||
int idz, id_large;
|
||||
float2 sarray_val;
|
||||
for(int id = 0; id < Npos; id++)
|
||||
{
|
||||
if (useGlobal) {
|
||||
// fast const memory based version
|
||||
idz = gC_ind_read[id]-1; // go only through some of the indices
|
||||
id_large = gC_pos_X[idz]+idx + Np_ox*(gC_pos_Y[idz]+idy);
|
||||
} else {
|
||||
// slower global memory based version
|
||||
idz = ind_read[id]-1; // go only through some of the indices
|
||||
id_large = pos_X[idz]+idx + Np_ox*(posY[idz]+idy);
|
||||
}
|
||||
int id_small = idx + Np_px*idy ;
|
||||
if (!isFlat)
|
||||
id_small = id_small + Np_px*Np_py*idz ;
|
||||
|
||||
// prevent extra memory load
|
||||
sarray_val = (isFlat && (idz > 0)) ? sarray_val: sarray[ id_small ];
|
||||
|
||||
|
||||
//larray[id_large].x += sarray_val.x;
|
||||
//larray[id_large].y += sarray_val.y;
|
||||
//__syncthreads();
|
||||
|
||||
// slowest step, without atomicAdd it misses some values
|
||||
atomicAdd(&larray[id_large].x ,sarray_val.x);
|
||||
atomicAdd(&larray[id_large].y ,sarray_val.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
|
||||
|
||||
int i ;
|
||||
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
|
||||
char const * const errMsg = "Invalid input to MEX file.";
|
||||
|
||||
// Check for proper number of arguments.
|
||||
if (nrhs != 5)
|
||||
mexErrMsgTxt("Five input arguments required");
|
||||
|
||||
|
||||
// Input must be of type single.
|
||||
for (i=0; i < 2; i++) {
|
||||
if ( !mxIsGPUArray(prhs[i]) && !mxIsCell(prhs[i]) ){
|
||||
printf("Input %d is not cell array\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
// Input must be of type int16.
|
||||
for (i=2; i<4; i++){
|
||||
if (mxIsUint16(prhs[i]) != 1){
|
||||
printf("Input %d is not integer\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type uint16.");
|
||||
}
|
||||
}
|
||||
|
||||
// It cannot be one-dimensional
|
||||
if(mxGetNumberOfDimensions(prhs[0]) < 2) {
|
||||
printf("The 1st input argument must have at least two dimensions.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
|
||||
}
|
||||
// It cannot be more than 3-dimensional
|
||||
if(mxGetNumberOfDimensions(prhs[0]) > 3) {
|
||||
printf("The 1st input argument must have at most three dimensions.");
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
|
||||
}
|
||||
// Check that arrays are complex
|
||||
|
||||
const mxGPUArray * m_obj_proj = mxGPUCreateFromMxArray(prhs[0]);
|
||||
if ((mxGPUGetClassID(m_obj_proj) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("m_obj_proj\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
|
||||
const mxGPUArray * m_positions_x = mxGPUCreateFromMxArray(prhs[2]);
|
||||
if ((mxGPUGetClassID(m_positions_x) != mxUINT16_CLASS)) {
|
||||
mexPrintf("m_positions_x\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const uint16_T * p_positions_x = (uint16_T *)mxGPUGetDataReadOnly(m_positions_x);
|
||||
|
||||
const mxGPUArray * m_positions_y = mxGPUCreateFromMxArray(prhs[3]);
|
||||
if ((mxGPUGetClassID(m_positions_y) != mxUINT16_CLASS)) {
|
||||
mexPrintf("m_positions_y\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const uint16_T * p_positions_y = (uint16_T *)mxGPUGetDataReadOnly(m_positions_y);
|
||||
|
||||
if (!mxIsCell(prhs[1]) || !mxIsCell(prhs[4]))
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Object and indices has to be in cell/cells !! ");
|
||||
if (mxGetNumberOfElements(prhs[1]) != mxGetNumberOfElements(prhs[4]))
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","Number of objects != number of indices ");
|
||||
|
||||
cuint Ncells = mxGetNumberOfElements(prhs[1]);
|
||||
const unsigned int Np_pp = mxGPUGetNumberOfElements(m_positions_y);
|
||||
|
||||
if (Np_pp < MAX_IND_READ) {
|
||||
cudaMemcpyToSymbol(gC_pos_X, p_positions_x, Np_pp*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
|
||||
cudaMemcpyToSymbol(gC_pos_Y, p_positions_y, Np_pp*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
|
||||
checkLastError("after cudaMemcpyToSymbol pos");
|
||||
}
|
||||
|
||||
for (int l=0; l<Ncells; l++)
|
||||
{
|
||||
|
||||
// read the cell content
|
||||
mxArray * mx_object = mxGetCell(prhs[1],l);
|
||||
mxArray * mx_ind = mxGetCell(prhs[4],l);
|
||||
|
||||
int N_ok = mxGetNumberOfElements(mx_ind);
|
||||
if(N_ok == 0)
|
||||
continue;
|
||||
|
||||
mxGPUArray * m_object = const_cast<mxGPUArray*>(mxGPUCreateFromMxArray(mx_object)); // mxGPUCopyFromMxArray(prhs[1]);
|
||||
if ((mxGPUGetClassID(m_object) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("m_object\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
|
||||
if (mxGPUGetComplexity(m_object) != mxGPUGetComplexity(m_obj_proj)) {
|
||||
mexPrintf("m_object and m_obj_proj complexity has to be the same \n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const mxGPUArray * m_ind_ok = mxGPUCreateFromMxArray(mx_ind);
|
||||
if ((mxGPUGetClassID(m_ind_ok) != mxUINT16_CLASS)) {
|
||||
mexPrintf("m_ind_ok\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const uint16_T * p_ind_ok = (uint16_T *)mxGPUGetDataReadOnly(m_ind_ok);
|
||||
|
||||
|
||||
|
||||
// Get dimension of probe and object
|
||||
const unsigned int Ndims = (unsigned int)mxGPUGetNumberOfDimensions(m_obj_proj);
|
||||
const mwSize * Np_o = mxGPUGetDimensions(m_object);
|
||||
const mwSize * Np_p = mxGPUGetDimensions(m_obj_proj);
|
||||
const unsigned int Npos = mxGPUGetNumberOfElements(m_ind_ok);
|
||||
|
||||
//mexPrintf("Ndims %i Np_o %i %i Np_p %i %i %i Npos %i \n " ,Ndims,Np_o[0],Np_o[1],Np_p[0],Np_p[1],Np_p[3],Npos);
|
||||
|
||||
|
||||
|
||||
|
||||
if (Ndims == 3 && Npos > Np_p[2]) {
|
||||
printf("wrong size of update / positions %i", Ndims);
|
||||
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
|
||||
}
|
||||
|
||||
|
||||
if (Npos > MAX_IND_READ) {
|
||||
//mexPrintf( "More than %i positions may be slow \n", MAX_IND_READ);
|
||||
} else {
|
||||
cudaMemcpyToSymbol(gC_ind_read, p_ind_ok, Npos*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
|
||||
checkLastError("after cudaMemcpyToSymbol pos");
|
||||
}
|
||||
|
||||
|
||||
// Choose a reasonably sized number of threads in each dimension for the block.
|
||||
int const threadsPerBlockEachDim = 32;
|
||||
// Compute the thread block and grid sizes based on the board dimensions.
|
||||
int const blocksPerGrid_M = (Np_p[0] + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
int const blocksPerGrid_N = (Np_p[1] + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
int const blocksPerGrid_O = 1;
|
||||
|
||||
dim3 const dimBlock(blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
|
||||
dim3 const dimThread(threadsPerBlockEachDim, threadsPerBlockEachDim, 1);
|
||||
|
||||
checkLastError("after dimThread");
|
||||
|
||||
checkLastError("after cudaMemcpyToSymbol");
|
||||
|
||||
const bool isFlat = (Ndims == 2);
|
||||
const bool isComplex = mxGPUGetComplexity(m_obj_proj) == mxCOMPLEX;
|
||||
// ================== call the right kernel ===================
|
||||
if (isComplex) {
|
||||
const float2 * p_obj_proj = (float2 *)mxGPUGetDataReadOnly(m_obj_proj);
|
||||
float2 * p_object = (float2 *)mxGPUGetData(m_object);
|
||||
if (Np_pp < MAX_IND_READ)
|
||||
addToArray_c<true><<<dimBlock, dimThread>>>(p_obj_proj,p_object, p_ind_ok, p_positions_x,p_positions_y ,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos, isFlat);
|
||||
else
|
||||
addToArray_c<false><<<dimBlock, dimThread>>>(p_obj_proj,p_object, p_ind_ok, p_positions_x,p_positions_y ,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos, isFlat);
|
||||
} else {
|
||||
const float * p_obj_proj = (float *)mxGPUGetDataReadOnly(m_obj_proj);
|
||||
float * p_object = (float *)mxGPUGetData(m_object);
|
||||
if (Np_pp < MAX_IND_READ)
|
||||
addToArray_r<true><<<dimBlock, dimThread>>>(p_obj_proj,p_object, p_ind_ok, p_positions_x,p_positions_y ,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos, isFlat);
|
||||
else
|
||||
addToArray_r<false><<<dimBlock, dimThread>>>(p_obj_proj,p_object, p_ind_ok, p_positions_x,p_positions_y ,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos, isFlat);
|
||||
}
|
||||
|
||||
checkLastError("after kernel");
|
||||
|
||||
mxGPUDestroyGPUArray(m_object);
|
||||
mxGPUDestroyGPUArray(m_ind_ok);
|
||||
}
|
||||
|
||||
cudaThreadSynchronize();
|
||||
|
||||
// plhs[0] = mxGPUCreateMxArrayOnGPU(m_object);
|
||||
mxGPUDestroyGPUArray(m_obj_proj);
|
||||
mxGPUDestroyGPUArray(m_positions_x);
|
||||
mxGPUDestroyGPUArray(m_positions_y);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user