//------------------------------------------------------------------------------
int pop(Workers& workers) { 
    assert(workers.size() > 0);
    std::set< worker_info >::iterator back = --workers.end();
    const int ret = back->id();
    workers.erase(back);
    return ret;
}
예제 #2
0
 inline unit_t getCount() const throw()
 {
     unit_t count = 0;
     for(size_t i=workers.size();i>0;--i)
     {
         count += workers[i]->count;
     }
     return count;
 }
예제 #3
0
 void saveXYZ( ios::ostream &fp ) const
 {
     unsigned np = 0;
     const size_t nw = workers.size();
     for(size_t i=nw;i>0;--i)
     {
         np += workers[i]->running.size;
     }
     fp("%u\n", np);
     fp("\n");
     for(size_t i=nw;i>0;--i)
     {
         for(const Particle *p=workers[i]->running.head;p;p=p->next)
         {
             const char *id = "H";
             if(p->kind) id = "Li";
             fp("%s %g %g %g\n",id,p->r.x,p->r.y,p->r.z);
         }
     }
 }
예제 #4
0
    inline void setup() throw()
    {
        // gather particles
        const size_t nw = workers.size();
        running.merge_back(waiting);
        for(size_t i=nw;i>0;--i)
        {
            running.merge_back(workers[i]->running);
            running.merge_back(workers[i]->waiting);
        }
        core::merging<Particle>::sort(running, Particle::compareByAddress, NULL);

        // initialize them
        for(Particle *p=running.head;p;p=p->next)
        {
            p->r.x = -Box.x/2 + Box.x * ran();
            p->r.y = -Box.y/2 + Box.y * ran();
            p->r.z = -Box.z * ran();
            p->status = Particle::InReservoir;
            p->kind   = 0;
            p->inReservoir();
        }

        // dispatch particles
        const size_t np = running.size;
        for(size_t i=0;i<nw;++i)
        {
            size_t offset = 0;
            size_t length = np;
            parallel::basic_split(i,nw, offset, length);
            Worker &w = *workers[i+1];
            while(length-->0)
            {
                w.running.push_back(running.pop_front());
            }
            //std::cerr << "#running[" << i+1 << "]=" << w.running.size << std::endl;
        }
    }
//------------------------------------------------------------------------------
int main(int argc, char** argv) {
    if(argc < 3) {
        std::cout << "usage: "
                  << argv[0] << " <frontend address> <backend address>"
                  << std::endl;
        return 0;
    }
    const char* FRONTEND_URI = argv[1];
    const char* BACKEND_URI  = argv[2];
    const int MAX_REQUESTS = 100;
  
    //create communication objects   	
    void* context = zmq_ctx_new();
    assert(context);
    void* frontend = zmq_socket(context, ZMQ_ROUTER);
    assert(frontend);
    void* backend = zmq_socket(context, ZMQ_ROUTER);
    assert(backend);
    assert(zmq_bind(frontend, FRONTEND_URI) == 0);
    assert(zmq_bind(backend, BACKEND_URI) == 0);

    //workers ordered queue 
    Workers workers;
 
    int worker_id = -1;
    int client_id = -1;
    int rc = -1;
    std::vector< char > request(0x100, 0);
    std::vector< char > reply(0x100, 0);
    int serviced_requests = 0;
    //loop until max requests servided
    while(serviced_requests < MAX_REQUESTS) {
        zmq_pollitem_t items[] = {
            {backend, 0, ZMQ_POLLIN, 0},
            {frontend, 0, ZMQ_POLLIN, 0}};
        //remove all workers that have not been active for a
        //time > expiration interval
        //XXX TODO: TEST    
        purge(workers, EXPIRATION_INTERVAL);        
        //XXX    
        //poll for incoming requests: if no workers are available
        //only poll for workers(backend) since there is no point
        //in trying to service a client request without active
        //workers
        rc = zmq_poll(items, workers.size() > 0 ? 2 : 1,
                      TIMEOUT);
        if(rc == -1) break;
        //data from workers
        if(items[0].revents & ZMQ_POLLIN) {    
            assert(zmq_recv(backend, &worker_id, sizeof(worker_id), 0) > 0);
            assert(zmq_recv(backend, 0, 0, 0) == 0);       
            assert(zmq_recv(backend, &client_id, sizeof(client_id), 0) > 0);
            //add worker to list of available workers
            push(workers, worker_id);
            assert(workers.size() > 0);
            //of not a 'ready' message forward message to frontend
            //workers send 'ready' messages when either 
            if(client_id != WORKER_READY) {
                int seq_id = -1;
                assert(zmq_recv(backend, 0, 0, 0) == 0);
                rc = zmq_recv(backend, &seq_id, sizeof(seq_id), 0);
                assert(rc > 0);
                rc = zmq_recv(backend, &reply[0], reply.size(), 0);
                assert(rc > 0);
                zmq_send(frontend, &client_id, sizeof(client_id), ZMQ_SNDMORE);
                zmq_send(frontend, 0, 0, ZMQ_SNDMORE);
                zmq_send(frontend, &seq_id, sizeof(seq_id), ZMQ_SNDMORE);
                zmq_send(frontend, &reply[0], rc, 0);
                ++serviced_requests;
            } 
        } 
        //request from clients
        if(items[1].revents & ZMQ_POLLIN) { 
            int seq_id = -1;
            //receive request |client id|<null>|request id|data|
            zmq_recv(frontend, &client_id, sizeof(client_id), 0);
            zmq_recv(frontend, 0, 0, 0);
            rc = zmq_recv(frontend, &seq_id, sizeof(seq_id), 0);
            assert(rc > 0);
            const int req_size = zmq_recv(frontend, &request[0],
                                          request.size(), 0);
            assert(req_size > 0);
            //take worker from list and forward request to it
            worker_id = pop(workers);
            assert(worker_id > 0);
            zmq_send(backend, &worker_id, sizeof(worker_id), ZMQ_SNDMORE);
            zmq_send(backend, 0, 0, ZMQ_SNDMORE);
            zmq_send(backend, &client_id, sizeof(client_id), ZMQ_SNDMORE);
            zmq_send(backend, 0, 0, ZMQ_SNDMORE);
            zmq_send(backend, &seq_id, sizeof(seq_id), ZMQ_SNDMORE);
            zmq_send(backend, &request[0], req_size, 0);         
        } 
        const int hb = HEARTBEAT; //capturing HEARTBEAT directly generates
                                  //a warning because the lambda function should
                                  //not capture a variable with non-automatic
                                  //storage
        //send heartbeat request to all workers: workers reply to such request
        //with a 'ready' message
        std::for_each(workers.begin(),
                      workers.end(),
                      [backend, hb](const worker_info& wi) {
                          const int id = wi.id();
                          zmq_send(backend, &id,
                                   sizeof(id), ZMQ_SNDMORE);
                          zmq_send(backend, 0, 0, ZMQ_SNDMORE);
                          zmq_send(backend, &hb, sizeof(hb), 0);            
                      });
        

    }
    zmq_close(frontend);
    zmq_close(backend);
    zmq_ctx_destroy(context);
    return 0;
}