From 49ca54674e5430d7ba1e13119528a2875d6507b4 Mon Sep 17 00:00:00 2001 From: karius Date: Fri, 15 Jan 2021 18:54:43 +0100 Subject: [PATCH] further steps for alignment protocol --- Engine.cu | 1 - FittingProtocol.cu | 63 +---------------- FittingProtocol.h | 13 +--- GPUManager.o | Bin 685200 -> 685248 bytes GPUObject.o | Bin 216032 -> 216040 bytes Makefile.test | 18 +++-- Node.cu | 7 -- Node.h | 46 +++++++------ NodeLoadPdb.cu | 16 +++-- NodeLoadPdb.h | 2 + Parameter.cu | 7 -- Parameter.h | 3 +- ParameterPaths.cu | 11 +++ ParameterPaths.h | 5 +- ParameterSet.cu | 44 ++++++++++-- ParameterSet.h | 22 +++++- Particles.cu | 168 ++++++++++++++++++++++----------------------- Particles.h | 28 ++++---- Score.cu | 17 ----- Score.h | 33 +++++---- Scoring.h | 2 - Slot.cu | 1 - Slot.h | 14 ++-- cuda_core.cu | 6 -- test.cu | 72 +++++++++++++++++-- testareal.cu | 1 - util.h | 8 +++ 27 files changed, 331 insertions(+), 277 deletions(-) delete mode 100644 Node.cu delete mode 100644 Slot.cu diff --git a/Engine.cu b/Engine.cu index c1488a7..7a4b2bd 100644 --- a/Engine.cu +++ b/Engine.cu @@ -8,7 +8,6 @@ #include #include #include -#include Engine::Engine() { _workerthreads.resize(_gpumanager.numGPUS()); diff --git a/FittingProtocol.cu b/FittingProtocol.cu index 29cd967..5b02037 100644 --- a/FittingProtocol.cu +++ b/FittingProtocol.cu @@ -6,74 +6,13 @@ */ #include -void FittingProtocol::_determine_gpu_resources(void){ - //memory management library - nvmlInit_v2(); - cudaGetDeviceCount(&_num_devices); - _device_handles.resize(_num_devices); - _device_memory_infos.resize(_num_devices); - for (int i=0;i<_num_devices;i++){ - nvmlDeviceGetHandleByIndex_v2(i,&_device_handles[i]); - nvmlDeviceGetMemoryInfo(_device_handles[i], &_device_memory_infos[i]); - } - CudaCheckError(); -} -FittingProtocol::FittingProtocol() { - _determine_gpu_resources(); -} +FittingProtocol::FittingProtocol() {} -void FittingProtocol::addQueryFromPdb(const char * file_name){ - if (file_exists(file_name)){ - Query query = Query::fromPdb(file_name); - queries.push_back(query); - } -} -void FittingProtocol::loadTarget(int gpu_index){ - int ret = 0; - if(gpu_index < _num_devices){ - if(_device_memory_infos[gpu_index].free > target.getGpuMem()){ - ret += target.loadToGpu(gpu_index); - if (ret == 0){ - std::cout << "Target has been loaded to device of index " << gpu_index << "..." << std::endl; - } - } - } - else{ - std::cout << "Gpu Index " << gpu_index << " does not match the number of devices ..." << std::endl; - } -} - -void FittingProtocol::loadQueries(int gpu_index){ - int error = 0; - for (Query query: queries){ - if(_device_memory_infos[gpu_index].free > query.getGpuMem()){ - error += query.loadToGpu(gpu_index); - if (error == 0){ - std::cout << "Queries have been loaded to device of index " << gpu_index << "..." << std::endl; - } - } - } -} - -void FittingProtocol::printGPUInfo(void){ - printf("Found %i devices ...\n",_num_devices); - printf("-------------------------------------\n"); - for (int i=0;i<_num_devices;i++){ - printf("Device %i:\n",i); - printf("Total Memory: %u bytes\n",_device_memory_infos[i].total); - printf("-------------------------------------\n"); - } -} FittingProtocol::~FittingProtocol() { // TODO Auto-generated destructor stub } -void FittingProtocol::setFileTarget(const char * file_name){ - if (file_exists(file_name)){ - target = Target::fromMrc(file_name); - } -} diff --git a/FittingProtocol.h b/FittingProtocol.h index 629f77f..9027426 100644 --- a/FittingProtocol.h +++ b/FittingProtocol.h @@ -8,8 +8,6 @@ #ifndef FITTINGPROTOCOL_H_ #define FITTINGPROTOCOL_H_ -#include -#include //#include #include #include @@ -17,19 +15,14 @@ #include #include #include +#include class FittingProtocol { public: FittingProtocol(); - void setFileTarget(const char * file_name); - void addQueryFromPdb(const char * file_name); + void generateScorings(std::vector &scorings); + static void run(); virtual ~FittingProtocol(); - void printGPUInfo(void); - Target target; - void loadTarget(int gpu_index); - void loadQueries(int gpu_index); - std::vector queries; -// std::vector scores; private: GPUManager _manager; }; diff --git a/GPUManager.o b/GPUManager.o index 048349ff3c2193785ca61c3b968cb971fb1c2840..b0ab4f777ddef083104cda8598b9b8985e2b7321 100644 GIT binary patch delta 83474 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 diff --git a/GPUObject.o b/GPUObject.o index c73bbf59cfb01cc625a8a26c98b321c0a8adb13a..2ea207d629860ee7ae9171d9b37e062061c3e2df 100644 GIT binary patch delta 28460 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 delta 27857 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 lrINkU+d1!$w-@&?PN80G+|S #include -#include -#include #include +#include #include -template -class Node : public GPUObject{ +template +class Node : public GPUObject { public: - Node(){}; - ~Node() {}; + Node(Engine * _engine){ + this->_manager = &_engine->_gpumanager; + } ParameterSet * own_paras = nullptr; - ParameterSet memory; - void processRequest(const ParameterSet ¶_set); - void setGPUManager(GPUManager * manager){ - this->_manager = manager; - if (input != nullptr){ - input->_manager = manager; - } - if (output != nullptr){ - output->_manager = manager; - } + static void requestParameters(Node * node,ParameterSet * para_set){ + node->own_paras->print(); + printf("Precursor accessible: %s\n",node->precursor != nullptr ? "True": "False"); + if (node->precursor != nullptr) + requestParameters(node->precursor,para_set); + if (node->own_paras != nullptr) + para_set->addParameterSet(node->own_paras); } - Slot * input = nullptr; - Slot * output = nullptr; + ParameterSet memory; + //this shitty implementation is just for the compiler + OUTPUT * request(ParameterSet ¶_set){return nullptr;}; + Slot input; + Slot output; +// OUTPUT * output = new OUTPUT; +// void setPrecursor(void * _precursor){precursor = _precursor;}; +// void * precursor = nullptr; + ~Node(){}; }; + + + #endif /* NODE_H_ */ diff --git a/NodeLoadPdb.cu b/NodeLoadPdb.cu index 615c697..e623ee6 100644 --- a/NodeLoadPdb.cu +++ b/NodeLoadPdb.cu @@ -10,17 +10,21 @@ #include #include #include -#include -#include +#include -NodeLoadPdb::NodeLoadPdb(Engine * _engine){ - ParameterSet * set_para = new ParameterSet(); +NodeLoadPdb::NodeLoadPdb(Engine * _engine): Node(_engine){ + ParameterSet * set_para = new ParameterSet; ParameterPaths * para_paths = new ParameterPaths("pdb_paths"); set_para->addParameter(para_paths); own_paras = set_para; - output = new Slot(true); +} - setGPUManager(&_engine->_gpumanager); +Particles * NodeLoadPdb::request(ParameterSet ¶_set){ + if (para_set.containsParameter("pdb_paths")){ + ParameterPaths * parameter = dynamic_cast(para_set.getParameter("pdb_paths")); +// Particles::from_pdb(output,parameter->getPath()); + } + return nullptr; } NodeLoadPdb::~NodeLoadPdb() { diff --git a/NodeLoadPdb.h b/NodeLoadPdb.h index 3eb83da..3440f1e 100644 --- a/NodeLoadPdb.h +++ b/NodeLoadPdb.h @@ -11,11 +11,13 @@ #include #include #include +#include #include class NodeLoadPdb: public Node{ public: NodeLoadPdb(Engine * _engine); + Particles * request(ParameterSet ¶_set); virtual ~NodeLoadPdb(); }; diff --git a/Parameter.cu b/Parameter.cu index ca6dba0..1ffe1ba 100644 --- a/Parameter.cu +++ b/Parameter.cu @@ -4,10 +4,3 @@ * Created on: Nov 27, 2020 * Author: kkarius */ - -#include - -Parameter::~Parameter() { - // TODO Auto-generated destructor stub -} - diff --git a/Parameter.h b/Parameter.h index c71cbc8..d19107b 100644 --- a/Parameter.h +++ b/Parameter.h @@ -15,8 +15,9 @@ public: Parameter(const char * name):_name(name){}; // Parameter(const char * name,float from, float to, float init):_name(name),_from(from),_to(to),_init(init){}; std::string name(void){return std::string(_name);} + virtual int getVolume(void) = 0; // float continuousValue(int i = 0){return _init;}; - virtual ~Parameter(); + virtual ~Parameter(){}; private: const char * _name = nullptr; // float _from = 0; diff --git a/ParameterPaths.cu b/ParameterPaths.cu index a7203ed..6038a36 100644 --- a/ParameterPaths.cu +++ b/ParameterPaths.cu @@ -6,8 +6,19 @@ */ #include +#include +#include ParameterPaths::~ParameterPaths() { // TODO Auto-generated destructor stub } +void ParameterPaths::addPath(const char * path){ + if (file_exists(path) && _paths.end() == std::find(_paths.begin(),_paths.end(),path)){ + _paths.push_back(path); + } +} + +int ParameterPaths::getVolume(){ + return _paths.size(); +} diff --git a/ParameterPaths.h b/ParameterPaths.h index ac231f9..c57e828 100644 --- a/ParameterPaths.h +++ b/ParameterPaths.h @@ -13,7 +13,10 @@ class ParameterPaths : public Parameter { public: - ParameterPaths(const char * _name):Parameter(_name){}; + ParameterPaths(const char * name):Parameter(name){}; + const char * getPath(int index = 0){return _paths[index];} + void addPath(const char * path); + int getVolume(void); virtual ~ParameterPaths(); private: std::vector _paths; diff --git a/ParameterSet.cu b/ParameterSet.cu index 3935768..dfd215c 100644 --- a/ParameterSet.cu +++ b/ParameterSet.cu @@ -6,13 +6,47 @@ */ #include +#include -ParameterSet::ParameterSet() { - // TODO Auto-generated constructor stub - +int ParameterSet::getVolume(void){ + int ret = 1; + for (auto const &par:_parameters){ + ret *= par.second->getVolume(); + } + for (ParameterSet * parset:_parameter_sets){ + ret *= parset->getVolume(); + } + return ret; } -ParameterSet::~ParameterSet() { - // TODO Auto-generated destructor stub +int ParameterSet::getMultiIndexSize(void){ + return _parameters.size() + _parameter_sets.size(); } +std::vector ParameterSet::getMultiIndex(int i){ + std::vector ret(_parameters.size() + _parameter_sets.size()); + int p = _parameters.size(); + int ps = _parameter_sets.size(); + int d = p + ps; + std::vector volumes(d); + for (int j = 0;jgetVolume(); + } + for (int j = 0;jgetVolume(); + } + int l = 0; + int v; + int e; + for (int j = 0;j #include #include +#include class ParameterSet { public: - ParameterSet(); + ParameterSet(){}; void addParameter(Parameter * parameter){_parameters[parameter->name()] = parameter;} + void addParameterSet(ParameterSet * parameter_set){_parameter_sets.push_back(parameter_set);}; Parameter * getParameter(const char * name){return _parameters[std::string(name)];} - virtual ~ParameterSet(); + bool containsParameter(const char * name){return bool(_parameters.end() != _parameters.find(name));} + int getVolume(void); + int getMultiIndexSize(void); + std::vector getMultiIndex(int i); + void print(void){ + printf("========\n"); + printf("Parameters:\n"); + for (auto const& para: _parameters){ + printf("%s\n",para.first.c_str()); + } + printf("Parameter Sets:\n"); + for (auto const& para_set:_parameter_sets){ + para_set->print(); + } + } + virtual ~ParameterSet(){}; private: std::map _parameters; + std::vector _parameter_sets; }; #endif /* PARAMETERSET_H_ */ diff --git a/Particles.cu b/Particles.cu index da2d68e..96a9a73 100644 --- a/Particles.cu +++ b/Particles.cu @@ -8,21 +8,29 @@ #include Particles::Particles(){ - int error = 0; - h_bounding_box = (float *)malloc(6*sizeof(*h_bounding_box)); - error = int(cudaSuccess != cudaMalloc((void **) &d_bounding_box, 6*sizeof(*h_bounding_box))); - h_dimension = (float *) malloc(3*sizeof(*h_dimension)); - error = int(cudaSuccess != cudaMalloc((void **) &d_dimension,3*sizeof(*d_dimension))); - error = int(cudaSuccess != cudaMalloc((void **) &d_particle_count,sizeof(*d_particle_count))); - assert(error == 0); +// bool gpu_ok = true; +// h_bounding_box = (float *)malloc(6*sizeof(*h_bounding_box)); +// gpu_ok &= blockMemory(this,gpu_index,d_bounding_box, 6*sizeof(*d_bounding_box),h_bounding_box,true); +// h_dimension = (float *) malloc(3*sizeof(*h_dimension)); +// gpu_ok &= blockMemory(this,gpu_index,d_dimension, 6*sizeof(*d_dimension),h_dimension,true); +// gpu_ok &= blockMemory(this,gpu_index,d_particle_count, sizeof(*d_particle_count),h_particle_count,true); +// assert(gpu_ok == true); } -Particles::~Particles() {} +bool Particles::createInstance(int gpu_index){ + Particles_Register instance; + bool gpu_ok = true; + instance.h_bounding_box = (float *)malloc(6*sizeof(*instance.h_bounding_box)); + gpu_ok &= blockMemory(this,gpu_index,instance.d_bounding_box, 6*sizeof(*instance.d_bounding_box),instance.h_bounding_box,true); + instance.h_dimension = (float *) malloc(3*sizeof(*instance.h_dimension)); + gpu_ok &= blockMemory(this,gpu_index,instance.d_dimension, 6*sizeof(*instance.d_dimension),instance.h_dimension,true); + gpu_ok &= blockMemory(this,gpu_index,instance.d_particle_count, sizeof(*instance.d_particle_count),instance.h_particle_count,true); + assert(gpu_ok == true); + _instance_registry[gpu_index] = instance; + return gpu_ok; +} -void Particles::set_particle_count(const size_t & count){ - m_particle_count = count; - cudaMemcpy(d_particle_count,&m_particle_count,sizeof(size_t),cudaMemcpyHostToDevice); -}; +Particles::~Particles() {} struct translate : public thrust::unary_function { @@ -33,80 +41,68 @@ struct translate : public thrust::unary_function } }; +//__host__ +//void Particles::center_on_density(float * const& h_coord_dim){ +// find_bounds(); +// float4 shift = {h_coord_dim[0]/2 - (h_bounding_box[0] + h_dimension[0]/2),h_coord_dim[1]/2 - (h_bounding_box[1] + h_dimension[1]/2),h_coord_dim[2]/2 - (h_bounding_box[2] + h_dimension[2]/2),0}; +// translate unary_function_shift; +// unary_function_shift.shift = shift; +// thrust::transform(thrust::device_pointer_cast(&d_data[0]),thrust::device_pointer_cast(&d_data[h_particle_count[0]-1]),thrust::device_pointer_cast(&d_data[0]),unary_function_shift); +// h_bounding_box[0] += shift.x; +// h_bounding_box[1] += shift.y; +// h_bounding_box[2] += shift.z; +// h_bounding_box[3] += shift.x; +// h_bounding_box[4] += shift.y; +// h_bounding_box[5] += shift.z; +// assert(cudaSuccess == cudaMemcpy(d_bounding_box,h_bounding_box,6*sizeof(*d_bounding_box),cudaMemcpyHostToDevice)); +//} -__host__ -void Particles::center_on_density(float * const& h_coord_dim){ - find_bounds(); - float4 shift = {h_coord_dim[0]/2 - (h_bounding_box[0] + h_dimension[0]/2),h_coord_dim[1]/2 - (h_bounding_box[1] + h_dimension[1]/2),h_coord_dim[2]/2 - (h_bounding_box[2] + h_dimension[2]/2),0}; - translate unary_function_shift; - unary_function_shift.shift = shift; - thrust::transform(thrust::device_pointer_cast(&d_data[0]),thrust::device_pointer_cast(&d_data[m_particle_count-1]),thrust::device_pointer_cast(&d_data[0]),unary_function_shift); - h_bounding_box[0] += shift.x; - h_bounding_box[1] += shift.y; - h_bounding_box[2] += shift.z; - h_bounding_box[3] += shift.x; - h_bounding_box[4] += shift.y; - h_bounding_box[5] += shift.z; - assert(cudaSuccess == cudaMemcpy(d_bounding_box,h_bounding_box,6*sizeof(*d_bounding_box),cudaMemcpyHostToDevice)); -} - -__host__ -void Particles::origin_to_center(){ - find_bounds(); - float4 shift = {-(h_bounding_box[3] + h_bounding_box[0])/2,-(h_bounding_box[4] + h_bounding_box[1])/2,-(h_bounding_box[5] + h_bounding_box[2])/2,0}; - translate unary_function_shift; - unary_function_shift.shift = shift; - thrust::transform(thrust::device_pointer_cast(&d_data[0]),thrust::device_pointer_cast(&d_data[m_particle_count-1]),thrust::device_pointer_cast(&d_data[0]),unary_function_shift); - h_bounding_box[0] += shift.x; - h_bounding_box[1] += shift.y; - h_bounding_box[2] += shift.z; - h_bounding_box[3] += shift.x; - h_bounding_box[4] += shift.y; - h_bounding_box[5] += shift.z; - assert(cudaSuccess == cudaMemcpy(d_bounding_box,h_bounding_box,6*sizeof(*d_bounding_box),cudaMemcpyHostToDevice)); -} - -Particles Particles::from_pdb(const char * file_path){ - Particles particles; - PdbReader reader(file_path); - particles.pdb_readers.push_back(&reader); - particles.set_particle_count(reader.get_atom_count()); - return particles; -} +//__host__ +//void Particles::origin_to_center(){ +// find_bounds(); +// float4 shift = {-(h_bounding_box[3] + h_bounding_box[0])/2,-(h_bounding_box[4] + h_bounding_box[1])/2,-(h_bounding_box[5] + h_bounding_box[2])/2,0}; +// translate unary_function_shift; +// unary_function_shift.shift = shift; +// thrust::transform(thrust::device_pointer_cast(&d_data[0]),thrust::device_pointer_cast(&d_data[h_particle_count[0]-1]),thrust::device_pointer_cast(&d_data[0]),unary_function_shift); +// h_bounding_box[0] += shift.x; +// h_bounding_box[1] += shift.y; +// h_bounding_box[2] += shift.z; +// h_bounding_box[3] += shift.x; +// h_bounding_box[4] += shift.y; +// h_bounding_box[5] += shift.z; +// assert(cudaSuccess == cudaMemcpy(d_bounding_box,h_bounding_box,6*sizeof(*d_bounding_box),cudaMemcpyHostToDevice)); +//} -void Particles::find_bounds(){ - float4 max = {FLT_MAX,FLT_MAX,FLT_MAX,0}; - float4 min = {0,0,0,0}; - float4 min_coords = thrust::reduce(thrust::device_pointer_cast(&d_data[0]),thrust::device_pointer_cast(&d_data[m_particle_count-1]),max,min_float4()); - float4 max_coords = thrust::reduce(thrust::device_pointer_cast(&d_data[0]),thrust::device_pointer_cast(&d_data[m_particle_count-1]),min,max_float4()); - h_bounding_box[0] = min_coords.x; - h_bounding_box[1] = min_coords.y; - h_bounding_box[2] = min_coords.z; - h_bounding_box[3] = max_coords.x; - h_bounding_box[4] = max_coords.y; - h_bounding_box[5] = max_coords.z; - assert(cudaSuccess == cudaMemcpy(d_bounding_box,h_bounding_box,6*sizeof(*d_bounding_box),cudaMemcpyHostToDevice)); - - //calc dimension - for (int i=0;i<3;i++) - h_dimension[i] = h_bounding_box[i+3] - h_bounding_box[i]; - assert(cudaSuccess == cudaMemcpy(d_dimension,h_dimension,3*sizeof(float),cudaMemcpyHostToDevice)); -} +//void Particles::from_pdb(Particles * const& particles, const char * file_path){ +// PdbReader reader(file_path); +//// particles->pdb_readers.push_back(&reader); +// particles->h_particle_count[0]=reader.get_atom_count(); +//} +// +//void Particles::find_bounds(){ +// float4 max = {FLT_MAX,FLT_MAX,FLT_MAX,0}; +// float4 min = {0,0,0,0}; +// float4 min_coords = thrust::reduce(thrust::device_pointer_cast(&d_data[0]),thrust::device_pointer_cast(&d_data[h_particle_count[0]-1]),max,min_float4()); +// float4 max_coords = thrust::reduce(thrust::device_pointer_cast(&d_data[0]),thrust::device_pointer_cast(&d_data[h_particle_count[0]-1]),min,max_float4()); +// h_bounding_box[0] = min_coords.x; +// h_bounding_box[1] = min_coords.y; +// h_bounding_box[2] = min_coords.z; +// h_bounding_box[3] = max_coords.x; +// h_bounding_box[4] = max_coords.y; +// h_bounding_box[5] = max_coords.z; +// assert(cudaSuccess == cudaMemcpy(d_bounding_box,h_bounding_box,6*sizeof(*d_bounding_box),cudaMemcpyHostToDevice)); +// +// //calc dimension +// for (int i=0;i<3;i++) +// h_dimension[i] = h_bounding_box[i+3] - h_bounding_box[i]; +// assert(cudaSuccess == cudaMemcpy(d_dimension,h_dimension,3*sizeof(float),cudaMemcpyHostToDevice)); +//} -__host__ -std::pair Particles::rotationally_safe_bounding_box(void){ - std::pair ret; - float d = sqrtf(powf(h_bounding_box[3]-h_bounding_box[0],2) + powf(h_bounding_box[1]-h_bounding_box[4],2) + powf(h_bounding_box[2]-h_bounding_box[5],2))/2; - ret.first = make_float3(-d,-d,-d); - ret.second = make_float3(d,d,d); - return ret; -} -__device__ -void Particles::d_get_dimension(float *& d_dim){ - d_dim = d_dimension; -} - -void Particles::print_bounding_box(){ - printf("Bounding box lower left front: %f %f %f\n",h_bounding_box[0],h_bounding_box[1],h_bounding_box[2]); - printf("Bounding box upper right back: %f %f %f\n",h_bounding_box[3],h_bounding_box[4],h_bounding_box[5]); -} +//__host__ +//std::pair Particles::rotationally_safe_bounding_box(void){ +// std::pair ret; +// float d = sqrtf(powf(h_bounding_box[3]-h_bounding_box[0],2) + powf(h_bounding_box[1]-h_bounding_box[4],2) + powf(h_bounding_box[2]-h_bounding_box[5],2))/2; +// ret.first = make_float3(-d,-d,-d); +// ret.second = make_float3(d,d,d); +// return ret; +//} diff --git a/Particles.h b/Particles.h index fd016c7..0ae5e25 100644 --- a/Particles.h +++ b/Particles.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -35,31 +36,34 @@ #include #include +#include - -class Particles { -public: - Particles(); - virtual ~Particles(); - size_t particle_count(){return m_particle_count;}; - void set_particle_count(const size_t & count); - static Particles from_pdb(const char * file_path); - std::vector pdb_readers; - void find_bounds(void); - void print_bounding_box(void); +struct Particles_Register { float4 * h_data = nullptr; float4 * d_data = nullptr; float * h_bounding_box= nullptr; float * d_bounding_box= nullptr; float * d_dimension = nullptr; float * h_dimension = nullptr; + size_t * h_particle_count = nullptr; size_t * d_particle_count = nullptr; +}; + +class Particles: public GPUObject { +public: + Particles(); + bool createInstance(int gpu_index); + virtual ~Particles(); + static void from_pdb(Particles * const& particles, const char * file_path); +// std::vector pdb_readers; + void find_bounds(void); + void print_bounding_box(void); __host__ std::pair rotationally_safe_bounding_box(void); __host__ void center_on_density(float * const& h_coord_dim); __device__ void d_get_dimension(float *&); __host__ void origin_to_center(void); private: - size_t m_particle_count{0}; + std::map _instance_registry; }; #endif /* PARTICLES_H_ */ diff --git a/Score.cu b/Score.cu index 6f3c616..065d2dc 100644 --- a/Score.cu +++ b/Score.cu @@ -4,20 +4,3 @@ * Created on: Nov 26, 2020 * Author: kkarius */ - -#include - -Score::Score() { - // TODO Auto-generated constructor stub -} - -Score::Score(Target * const& target,Query * const& query){ - Score(); - this->target = target; - this->query = query; -} - -Score::~Score() { - // TODO Auto-generated destructor stub -} - diff --git a/Score.h b/Score.h index f0a524e..e40ee09 100644 --- a/Score.h +++ b/Score.h @@ -9,20 +9,29 @@ #define SCORE_H_ #include -#include -#include -#include -#include +#include +#include +#include +#include -class Score { +template +class Score: public GPUObject{ public: - Score(); - Score(Target * const&,Query * const&); - virtual ~Score(); - std::vector parameters; - Target * const& target = nullptr; - Query * const query = nullptr; - virtual MemoryResources requestTargetMemoryResources() = 0; + Score(Engine * _engine){ + this->_manager = &_engine->_gpumanager; + } + void score(QueryT * d_query,TargetT * d_target); + void requestParameters(ParameterSet * para_set){ + if (query_input != nullptr && target_input != nullptr ){ +// Node::requestParameters(dynamic_cast *>(query_input),para_set); +// Node::requestParameters(dynamic_cast *>(target_input),para_set); + } + para_set->addParameterSet(own_paras); + } + Slot * query_input = nullptr; + Slot * target_input = nullptr; + virtual ~Score(){}; + ParameterSet * own_paras = new ParameterSet; }; #endif /* SCORE_H_ */ diff --git a/Scoring.h b/Scoring.h index 33fe9c9..52c57cc 100644 --- a/Scoring.h +++ b/Scoring.h @@ -8,8 +8,6 @@ #ifndef SCORING_H_ #define SCORING_H_ -#include -#include #include class Scoring { diff --git a/Slot.cu b/Slot.cu deleted file mode 100644 index 8b13789..0000000 --- a/Slot.cu +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Slot.h b/Slot.h index 9eebdc0..28623fe 100644 --- a/Slot.h +++ b/Slot.h @@ -1,23 +1,21 @@ /* * Slot.h * - * Created on: Dec 17, 2020 + * Created on: Jan 1, 2021 * Author: kkarius */ #ifndef SLOT_H_ #define SLOT_H_ -#include -#include - template -class Slot: public GPUObject { +class Slot { public: - Slot( bool _is_output):is_output(_is_output){}; + Slot(){}; + T * content = nullptr; + Slot * connect = nullptr; ~Slot(){}; - T * request(ParameterSet para_set); - bool is_output = true; }; + #endif /* SLOT_H_ */ diff --git a/cuda_core.cu b/cuda_core.cu index b3d0a4a..edd3b20 100644 --- a/cuda_core.cu +++ b/cuda_core.cu @@ -1778,12 +1778,6 @@ void reduce(T * d_data, size_t num, T * result){ if (tid == 0){*result = rshared[0];} } -void pdb_to_density(const char * pdb_path,){ - //prepare gpu - - //call kernels -} - void score_envelope(boost::filesystem::path in_kai_file_path, boost::filesystem::path in_mrc, float tau){ //general algorithm: diff --git a/test.cu b/test.cu index 43a0221..c361de1 100644 --- a/test.cu +++ b/test.cu @@ -25,17 +25,28 @@ //#include // //#include -#include -#include +//#include +//#include #include -#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include using namespace std::chrono_literals; BOOST_AUTO_TEST_CASE(general_engine_test) { printf(" ======================================== Engine Test =====================================\n"); printf(" ============================= ++++++++++++++++++++++++++++++++ ===========================\n"); - Engine engine; + AlignmentProtocol align_protocol("/data/tmp/test_rmfs"); + align_protocol.prepare(); +// Engine engine; // engine.startWorkers(); // engine.submitTask(std::shared_ptr(new Task("Yay0")),0); // engine.submitTask(std::shared_ptr(new Task("Yay1")),1); @@ -43,7 +54,58 @@ BOOST_AUTO_TEST_CASE(general_engine_test) // engine.submitTask(std::shared_ptr(new Task("Yay3")),3); // std::this_thread::sleep_for(1s); // engine.killWorkers(); - NodeLoadPdb loadpdb(&engine); + +// NodeLoadPdb load_pdb(&engine); +// NodeLoadMrc load_mrc(&engine); +// NodeDensityThreshold pdb_density_thresh(&engine,"pdb_density_thresh"); +// NodeDensityThreshold mrc_density_thresh(&engine,"mrc_density_thresh"); +// NodeMolecularDensity pdb_mol_density(&engine); +// ScoreCam cam_score(&engine); +// +// dynamic_cast(load_pdb.own_paras->getParameter("pdb_paths"))->addPath("test/tauA.pdb"); +// dynamic_cast(load_mrc.own_paras->getParameter("mrc_paths"))->addPath("test/tauA.mrc"); +// //LoadPdb --> MolDensity --> DensityThreshold --> +// // |---> CamScore +// //LoadMrc --> DensityThreshold -----------------> +// +// //connect inputs and outputs of nodes and scores +// load_pdb.output.connect = &pdb_mol_density.input; +// pdb_mol_density.output.connect = &pdb_density_thresh.input; +// load_mrc.output.connect = &mrc_density_thresh.input; +// +// cam_score.target_input = &mrc_density_thresh.output; +// cam_score.query_input = &pdb_density_thresh.output; + + //model combined parameter set ((pdb_path,rho0,t0),(mrc_path,t1)) +// ParameterSet combined_paras; +// ParameterSet pdb_line; +// ParameterSet mrc_line; +// +// pdb_line.addParameterSet(load_pdb.own_paras); +// pdb_line.addParameterSet(pdb_mol_density.own_paras); +// pdb_line.addParameterSet(pdb_density_thresh.own_paras); +// +// mrc_line.addParameterSet(load_mrc.own_paras); +// mrc_line.addParameterSet(mrc_density_thresh.own_paras); +// +// combined_paras.addParameterSet(&mrc_line); +// combined_paras.addParameterSet(&pdb_line); +// +// std::vector multi(combined_paras.getMultiIndexSize()); +// printf("Volume: %i\n",combined_paras.getVolume()); +// printf("MultiIndex Size: %i\n",combined_paras.getMultiIndexSize()); +// for (int i=0;ih_particle_count[0] << std::endl; // std::pair effective_translational_shift; // effective_translational_shift.first = {0,0,0}; // effective_translational_shift.second = {2,2,2}; diff --git a/testareal.cu b/testareal.cu index 0be98d9..279d1a6 100644 --- a/testareal.cu +++ b/testareal.cu @@ -271,7 +271,6 @@ struct M_alpha { float m23; float m33; char padding; - }; __global__ diff --git a/util.h b/util.h index cc3a622..6fa1688 100644 --- a/util.h +++ b/util.h @@ -47,6 +47,14 @@ inline void __cudaCheckError(const char *file, const int line) { return; } +#include + +inline bool dir_exists(const std::string &s) +{ + struct stat buffer; + return (stat (s.c_str(), &buffer) == 0); +} + inline bool file_exists (const std::string& name) { if (FILE *file = fopen(name.c_str(), "r")) { fclose(file); -- GitLab