Esempio n. 1
0
/*-------------------------------------------------------------------------*
 * PL_KEEP_REST_FOR_PROLOG                                                 *
 *                                                                         *
 * Update CP in choices points to be used by classical Prolog engine       *
 * (some CPB(b) have been set to Call_Prolog_Success due to Call_Prolog).  *
 *-------------------------------------------------------------------------*/
void
Pl_Keep_Rest_For_Prolog(WamWord *query_b)
{
  WamWord *b, *e, *query_e;

  for (b = B; b > query_b; b = BB(b))
    if (CPB(b) == Adjust_CP(Call_Prolog_Success))
      CPB(b) = CP;

  query_e = EB(query_b);

  for (e = EB(B); e > query_e; e = EE(e))
    if (CPE(e) == Adjust_CP(Call_Prolog_Success))
      CPE(e) = CP;
}
Esempio n. 2
0
void *run_server(void *arg)
{
	struct thread_params params = *(struct thread_params *) arg;
	int srv_gid = params.id;	/* Global ID of this server thread */
	int clt_gid = srv_gid;	/* One-to-one connections */
	int ib_port_index = params.dual_port == 0 ? 0 : srv_gid % 2;

	struct hrd_ctrl_blk *cb = hrd_ctrl_blk_init(srv_gid,	/* local_hid */
		ib_port_index, -1, /* port_index, numa_node_id */
		1, params.use_uc,	/* conn qps, uc */
		NULL, BUF_SIZE, -1,	/* prealloc buf, buf size, key */
		0, 0, -1);	/* #dgram qps, buf size, shm key */

	memset((void *) cb->conn_buf, (uint8_t) srv_gid + 1, BUF_SIZE);

	char srv_name[HRD_QP_NAME_SIZE];
	sprintf(srv_name, "server-%d", srv_gid);
	hrd_publish_conn_qp(cb, 0, srv_name);

	printf("main: Server %d published. Waiting for client %d\n",
		srv_gid, clt_gid);

	char clt_name[HRD_QP_NAME_SIZE];
	struct hrd_qp_attr *clt_qp = NULL;
	sprintf(clt_name, "client-%d", clt_gid);

	while(clt_qp == NULL) {
		clt_qp = hrd_get_published_qp(clt_name);
		if(clt_qp == NULL) {
			usleep(200000);
		}
	}

	hrd_connect_qp(cb, 0, clt_qp);
	hrd_wait_till_ready(clt_name);

	printf("main: Server %d connected!\n", srv_gid);

	struct ibv_send_wr wr[MAX_POSTLIST], *bad_send_wr;
	struct ibv_sge sgl[MAX_POSTLIST];
	struct ibv_wc wc;
	long long nb_tx = 0;
	int w_i = 0;	/* Window index */
	int ret;

	/*
	 * The reads/writes at different postlist positions should be done to/from
	 * different cache lines.
	 */
	int offset = CACHELINE_SIZE;
	while(offset < params.size) {
		offset += CACHELINE_SIZE;
	}
	assert(offset * params.postlist <= BUF_SIZE);

	int opcode = params.do_read == 0 ? IBV_WR_RDMA_WRITE : IBV_WR_RDMA_READ;

	struct timespec start, end;
	clock_gettime(CLOCK_REALTIME, &start);
	double *latency_samples = (double *) malloc(NUM_LATENCY_SAMPLES * 
		sizeof(double));
	int lat_i = 0;	/* Latency sample index */

	while(1) {
		if(lat_i == NUM_LATENCY_SAMPLES) {
			break;
		}

		/* Post a list of work requests in a single ibv_post_send() */
		for(w_i = 0; w_i < params.postlist; w_i++) {
			wr[w_i].opcode = opcode;
			wr[w_i].num_sge = 1;
#if USE_POSTLIST == 1
			wr[w_i].next = (w_i == params.postlist - 1) ? NULL : &wr[w_i + 1];
#else
			wr[w_i].next = NULL;
#endif
			wr[w_i].sg_list = &sgl[w_i];

			wr[w_i].send_flags = (w_i == params.postlist - 1) ?
				IBV_SEND_SIGNALED : 0;
			if(w_i == 0 && nb_tx != 0) {
				hrd_poll_cq(cb->conn_cq[0], 1, &wc);

				clock_gettime(CLOCK_REALTIME, &end);
				double useconds = (end.tv_sec - start.tv_sec) * 1000000 + 
					(double) (end.tv_nsec - start.tv_nsec) / 1000;

				latency_samples[lat_i] = useconds;
				lat_i++;
				clock_gettime(CLOCK_REALTIME, &start);
			}

			wr[w_i].send_flags |= (params.do_read == 0) ? IBV_SEND_INLINE: 0;

			sgl[w_i].addr = (uint64_t) (uintptr_t) &cb->conn_buf[offset * w_i];
			sgl[w_i].length = params.size;
			sgl[w_i].lkey = cb->conn_buf_mr->lkey;

			wr[w_i].wr.rdma.remote_addr = clt_qp->buf_addr + (offset * w_i);
			wr[w_i].wr.rdma.rkey = clt_qp->rkey;

#if USE_POSTLIST == 0
			ret = ibv_post_send(cb->conn_qp[0], &wr[w_i], &bad_send_wr);
			CPE(ret, "ibv_post_send error", ret);
#endif

			nb_tx++;
		}
#if USE_POSTLIST == 1
		ret = ibv_post_send(cb->conn_qp[0], &wr[0], &bad_send_wr);
#endif
		CPE(ret, "ibv_post_send error", ret);

	}

	analyse(latency_samples);

	return NULL;
}
Esempio n. 3
0
void *run_client(void *arg)
{
	int ud_qp_i = 0;
	struct thread_params params = *(struct thread_params *) arg;

	/* 
	 * The local HID of a control block should be <= 64 to keep the SHM key low.
	 * But the number of clients over all machines can be larger.
	 */
	int clt_gid = params.id;	/* Global ID of this client thread */
	int clt_local_hid = clt_gid % params.num_threads;

	int srv_gid = clt_gid % NUM_SERVER_THREADS;
	int ib_port_index = params.dual_port == 0 ? 0 : srv_gid % 2;

	struct hrd_ctrl_blk *cb = hrd_ctrl_blk_init(clt_local_hid,
		ib_port_index, -1, /* port_index, numa_node_id */
		0, 0, /* conn qps, use uc */
		NULL, 0, -1,	/* prealloc conn buf, conn buf size, key */
		1, BUF_SIZE, -1);	/* num_dgram_qps, dgram_buf_size, key */

	/* Buffer to receive responses into */
	memset((void *) cb->dgram_buf, 0, BUF_SIZE);

	/* Buffer to send requests from */
	uint8_t *req_buf = malloc(params.size);
	assert(req_buf != 0);
	memset(req_buf, clt_gid, params.size);

	printf("main: Client %d waiting for server %d\n", clt_gid, srv_gid);

	struct hrd_qp_attr *srv_qp[NUM_UD_QPS] = {NULL};
	for(ud_qp_i = 0; ud_qp_i < NUM_UD_QPS; ud_qp_i++) {
		char srv_name[HRD_QP_NAME_SIZE];
		sprintf(srv_name, "server-%d-%d", srv_gid, ud_qp_i);
		while(srv_qp[ud_qp_i] == NULL) {
			srv_qp[ud_qp_i] = hrd_get_published_qp(srv_name);
			if(srv_qp[ud_qp_i] == NULL) {
				usleep(200000);
			}
		}
	}
	ud_qp_i = 0;

	printf("main: Client %d found server! Now posting SENDs.\n", clt_gid);

	/* We need only 1 ah because a client contacts only 1 server */
	struct ibv_ah_attr ah_attr = {
		.is_global = 0,
		.dlid = srv_qp[0]->lid,	/* All srv_qp have same LID */
		.sl = 0,
		.src_path_bits = 0,
		.port_num = cb->dev_port_id,
	};
	
	struct ibv_ah *ah = ibv_create_ah(cb->pd, &ah_attr);
	assert(ah != NULL);
	
	struct ibv_send_wr wr[MAX_POSTLIST], *bad_send_wr;
	struct ibv_wc wc[MAX_POSTLIST];
	struct ibv_sge sgl[MAX_POSTLIST];
	long long rolling_iter = 0;	/* For throughput measurement */
	long long nb_tx = 0;
	int w_i = 0;	/* Window index */
	int ret;

	struct timespec start, end;
	clock_gettime(CLOCK_REALTIME, &start);

	while(1) {
		if(rolling_iter >= M_2) {
			clock_gettime(CLOCK_REALTIME, &end);
			double seconds = (end.tv_sec - start.tv_sec) + 
				(double) (end.tv_nsec - start.tv_nsec) / 1000000000;
			printf("main: Client %d: %.2f Mops\n",
				clt_gid, rolling_iter / seconds);
			rolling_iter = 0;
		
			clock_gettime(CLOCK_REALTIME, &start);
		}

		for(w_i = 0; w_i < params.postlist; w_i++) {
			wr[w_i].wr.ud.ah = ah;
			wr[w_i].wr.ud.remote_qpn = srv_qp[ud_qp_i]->qpn;
			wr[w_i].wr.ud.remote_qkey = HRD_DEFAULT_QKEY;

			wr[w_i].opcode = IBV_WR_SEND_WITH_IMM;
			wr[w_i].num_sge = 1;
			wr[w_i].next = (w_i == params.postlist - 1) ? NULL : &wr[w_i + 1];
			wr[w_i].imm_data = 3185;
			wr[w_i].sg_list = &sgl[w_i];

			/*
			 * UNSIG_BATCH >= 2 * postlist ensures that we poll for a
			 * completed send() only after we have performed a signaled send().
			 */
			wr[w_i].send_flags = (nb_tx & UNSIG_BATCH_) == 0 ?
				IBV_SEND_SIGNALED : 0;
			if((nb_tx & UNSIG_BATCH_) == UNSIG_BATCH_) {
				hrd_poll_cq(cb->dgram_send_cq[0], 1, wc);
			}

			wr[w_i].send_flags |= IBV_SEND_INLINE;

			sgl[w_i].addr = (uint64_t) (uintptr_t) req_buf;
			sgl[w_i].length = params.size;

			rolling_iter++;
			nb_tx++;
		}

		ret = ibv_post_send(cb->dgram_qp[0], &wr[0], &bad_send_wr);
		CPE(ret, "ibv_post_send error", ret);

		HRD_MOD_ADD(ud_qp_i, NUM_UD_QPS);
	}

	return NULL;
}
Esempio n. 4
0
void *run_client(void *arg)
{
    int i;
    struct thread_params params = *(struct thread_params *) arg;
    int clt_gid = params.id;	/* Global ID of this client thread */
    int num_client_ports = params.num_client_ports;
    int num_server_ports = params.num_server_ports;

    /*
     * Ensure that all responses fit in dgram_buf. We post RECVs of size
     * CACHELINE_SIZE to ensure that the 8-byte counter and GRH fit.
     */
    assert(WINDOW_SIZE * CACHELINE_SIZE <= DGRAM_BUF_SIZE);

    /* This is the only port used by this client */
    int ib_port_index = params.base_port_index + clt_gid % num_client_ports;

    /*
     * The virtual server port index to connect to. This index is relative to
     * the server's base_port_index (that the client does not know).
     */
    int srv_virt_port_index = clt_gid % num_server_ports;

    /*
     * TODO: The client creates a connected buffer because the libhrd API
     * requires a buffer when creating connected queue pairs. This should be
     * fixed in the API.
     */
    struct hrd_ctrl_blk *cb = hrd_ctrl_blk_init(clt_gid,	/* local_hid */
                              ib_port_index, -1, /* port_index, numa_node_id */
                              1, 1,	/* #conn qps, uc */
                              NULL, 4096, -1,	/* prealloc conn buf, buf size, key */
                              1, DGRAM_BUF_SIZE, -1);	/* num_dgram_qps, dgram_buf_size, key */

    char mstr_qp_name[HRD_QP_NAME_SIZE];
    sprintf(mstr_qp_name, "master-%d-%d", srv_virt_port_index, clt_gid);

    char clt_conn_qp_name[HRD_QP_NAME_SIZE];
    sprintf(clt_conn_qp_name, "client-conn-%d", clt_gid);
    char clt_dgram_qp_name[HRD_QP_NAME_SIZE];
    sprintf(clt_dgram_qp_name, "client-dgram-%d", clt_gid);

    hrd_publish_conn_qp(cb, 0, clt_conn_qp_name);
    hrd_publish_dgram_qp(cb, 0, clt_dgram_qp_name);
    printf("main: Client %s published conn and dgram. Waiting for master %s\n",
           clt_conn_qp_name, mstr_qp_name);

    struct hrd_qp_attr *mstr_qp = NULL;
    while(mstr_qp == NULL) {
        mstr_qp = hrd_get_published_qp(mstr_qp_name);
        if(mstr_qp == NULL) {
            usleep(200000);
        }
    }

    printf("main: Client %s found master! Connecting..\n", clt_conn_qp_name);
    hrd_connect_qp(cb, 0, mstr_qp);
    hrd_wait_till_ready(mstr_qp_name);

    /* Start the real work */
    int ret;
    long long req_buf = 1;	/* Any non-zero number will do */

    /* Some tracking info */
    int ws[NUM_WORKERS] = {0};	/* Window slot to use for a worker */

    struct ibv_send_wr wr, *bad_send_wr;
    struct ibv_sge sgl;
    struct ibv_wc wc[WINDOW_SIZE];

    struct ibv_recv_wr recv_wr[WINDOW_SIZE], *bad_recv_wr;
    struct ibv_sge recv_sgl[WINDOW_SIZE];

    long long rolling_iter = 0;	/* For throughput measurement */
    long long nb_tx = 0;	/* Total requests performed or queued */
    int wn = 0;	/* Worker number */

    struct timespec start, end;
    clock_gettime(CLOCK_REALTIME, &start);

    /* Fill the RECV queue */
    for(i = 0; i < WINDOW_SIZE; i++) {
        hrd_post_dgram_recv(cb->dgram_qp[0],
                            (void *) &cb->dgram_buf[i * CACHELINE_SIZE],	/* i < WINDOW_SIZE */
                            CACHELINE_SIZE, cb->dgram_buf_mr->lkey);
    }

    while(1) {
        if(rolling_iter >= K_512) {
            clock_gettime(CLOCK_REALTIME, &end);
            double seconds = (end.tv_sec - start.tv_sec) +
                             (double) (end.tv_nsec - start.tv_nsec) / 1000000000;
            printf("main: Client %d: %.2f Mops. nb_tx = %lld\n",
                   clt_gid, K_512 / seconds, nb_tx);

            rolling_iter = 0;

            clock_gettime(CLOCK_REALTIME, &start);
        }

        /* Re-fill depleted RECVs */
        if(nb_tx % WINDOW_SIZE == 0 && nb_tx > 0) {
            for(i = 0; i < WINDOW_SIZE; i++) {
                recv_sgl[i].length = DGRAM_BUF_SIZE;
                recv_sgl[i].lkey = cb->dgram_buf_mr->lkey;
                recv_sgl[i].addr = (uintptr_t) &cb->dgram_buf[i * CACHELINE_SIZE];

                recv_wr[i].sg_list = &recv_sgl[i];
                recv_wr[i].num_sge = 1;
                recv_wr[i].next = (i == WINDOW_SIZE - 1) ?
                                  NULL : &recv_wr[i + 1];
            }

            ret = ibv_post_recv(cb->dgram_qp[0], &recv_wr[0], &bad_recv_wr);
            CPE(ret, "ibv_post_recv error", ret);
        }

        if(nb_tx % WINDOW_SIZE == 0 && nb_tx > 0) {
            hrd_poll_cq(cb->dgram_recv_cq[0], WINDOW_SIZE, wc);
        }

        wn = nb_tx % NUM_WORKERS;	/* Choose a worker */

        /* Forge the RDMA work request */
        sgl.length = sizeof(long long);
        sgl.addr = (uint64_t) (uintptr_t) &req_buf;

        wr.opcode = IBV_WR_RDMA_WRITE;
        wr.num_sge = 1;
        wr.next = NULL;
        wr.sg_list = &sgl;

        wr.send_flags = (nb_tx & UNSIG_BATCH_) == 0 ? IBV_SEND_SIGNALED : 0;
        if((nb_tx & UNSIG_BATCH_) == UNSIG_BATCH_) {
            hrd_poll_cq(cb->conn_cq[0], 1, wc);
        }
        wr.send_flags |= IBV_SEND_INLINE;

        wr.wr.rdma.remote_addr = mstr_qp->buf_addr +
                                 OFFSET(wn, clt_gid, ws[wn]) * sizeof(long long);
        wr.wr.rdma.rkey = mstr_qp->rkey;

        ret = ibv_post_send(cb->conn_qp[0], &wr, &bad_send_wr);
        CPE(ret, "ibv_post_send error", ret);
        //printf("Client %d: sending request index %lld\n", clt_gid, nb_tx);

        rolling_iter++;
        nb_tx++;
        HRD_MOD_ADD(ws[wn], WINDOW_SIZE);
    }

    return NULL;
}
Esempio n. 5
0
void *run_server(void *arg)
{
    int i;
    struct thread_params params = *(struct thread_params *) arg;
    int srv_gid = params.id;	/* Global ID of this server thread */
    int ib_port_index = params.dual_port == 0 ? 0 : srv_gid % 2;

    struct hrd_ctrl_blk *cb = hrd_ctrl_blk_init(srv_gid,	/* local_hid */
                              ib_port_index, -1, /* port_index, numa_node_id */
                              0, 0,	/* conn qps, use uc */
                              NULL, 0, -1,	/* prealloc conn buf, conn buf size, key */
                              NUM_UD_QPS, BUF_SIZE, -1);	/* num_dgram_qps, dgram_buf_size, key */

    /* Buffer to receive requests into */
    memset((void *) cb->dgram_buf, 0, BUF_SIZE);

    /* Buffer to send responses from */
    uint8_t *resp_buf = malloc(params.size);
    assert(resp_buf != 0);
    memset(resp_buf, 1, params.size);

    /* Create an address handle for each client */
    struct ibv_ah *ah[NUM_CLIENTS];
    memset(ah, 0, NUM_CLIENTS * sizeof(uintptr_t));

    struct hrd_qp_attr *clt_qp[NUM_CLIENTS];

    /*
     * Connect this server to NUM_CLIENTS clients whose global IDs are the
     * same as this server's modulo 2. This ensures that the connected
     * clients are on the same port as the server.
     */
    for(i = 0; i < NUM_CLIENTS; i++) {
        char clt_name[HRD_QP_NAME_SIZE];

        /* ah[i] maps to client clt_id */
        int clt_id = params.dual_port == 0 ? i : 2 * i + (srv_gid % 2);
        sprintf(clt_name, "client-%d", clt_id);

        /* Get the UD queue pair for the ith client */
        clt_qp[i] = NULL;
        while(clt_qp[i] == NULL) {
            clt_qp[i] = hrd_get_published_qp(clt_name);
            if(clt_qp[i] == NULL) {
                usleep(200000);
            }
        }

        printf("main: Server %d got client %d (clt_id = %d) of %d clients.\n",
               srv_gid, i, clt_id, NUM_CLIENTS);

        struct ibv_ah_attr ah_attr = {
            .is_global = 0,
            .dlid = clt_qp[i]->lid,
            .sl = 0,
            .src_path_bits = 0,
            .port_num = cb->dev_port_id,
        };

        ah[i]= ibv_create_ah(cb->pd, &ah_attr);
        assert(ah[i] != NULL);
    }

    struct ibv_send_wr wr[MAX_POSTLIST], *bad_send_wr;
    struct ibv_wc wc[MAX_POSTLIST];
    struct ibv_sge sgl[MAX_POSTLIST];
    long long rolling_iter = 0;	/* For throughput measurement */
    long long nb_tx[NUM_UD_QPS] = {0};	/* For selective signaling */
    int ud_qp_i = 0;	/* Round-robin between QPs across postlists */
    int w_i = 0;	/* Window index */
    int ret;

    struct timespec start, end;
    clock_gettime(CLOCK_REALTIME, &start);

    while(1) {
        if(rolling_iter >= M_4) {
            clock_gettime(CLOCK_REALTIME, &end);
            double seconds = (end.tv_sec - start.tv_sec) +
                             (double) (end.tv_nsec - start.tv_nsec) / 1000000000;
            double my_tput = M_4 / seconds;
            printf("main: Server %d: %.2f Mops. \n", srv_gid, my_tput);
            params.tput[srv_gid] = my_tput;
            if(srv_gid == 0) {
                double total_tput = 0;
                for(i = 0; i < params.num_threads; i++) {
                    total_tput += params.tput[i];
                }
                hrd_red_printf("main: Total tput = %.2f Mops.\n", total_tput);
            }

            rolling_iter = 0;

            clock_gettime(CLOCK_REALTIME, &start);
        }

        for(w_i = 0; w_i < params.postlist; w_i++) {
            int cn = nb_tx[ud_qp_i] & NUM_CLIENTS_;

            wr[w_i].wr.ud.ah = ah[cn];
            wr[w_i].wr.ud.remote_qpn = clt_qp[cn]->qpn;
            wr[w_i].wr.ud.remote_qkey = HRD_DEFAULT_QKEY;

            wr[w_i].opcode = IBV_WR_SEND;
            wr[w_i].num_sge = 1;
            wr[w_i].next = (w_i == params.postlist - 1) ? NULL : &wr[w_i + 1];
            wr[w_i].sg_list = &sgl[w_i];

            wr[w_i].send_flags = ((nb_tx[ud_qp_i] & UNSIG_BATCH_) == 0) ?
                                 IBV_SEND_SIGNALED : 0;
            if((nb_tx[ud_qp_i] & UNSIG_BATCH_) == 0 && nb_tx[ud_qp_i] > 0) {
                hrd_poll_cq(cb->dgram_send_cq[ud_qp_i], 1, wc);
            }

            wr[w_i].send_flags |= IBV_SEND_INLINE;

            sgl[w_i].addr = (uint64_t) (uintptr_t) resp_buf;
            sgl[w_i].length = params.size;

            nb_tx[ud_qp_i]++;
            rolling_iter++;
        }

        ret = ibv_post_send(cb->dgram_qp[ud_qp_i], &wr[0], &bad_send_wr);
        CPE(ret, "ibv_post_send error", ret);

        /* Use a different QP for the next postlist */
        ud_qp_i++;
        if(ud_qp_i == NUM_UD_QPS) {
            ud_qp_i = 0;
        }
    }

    return NULL;
}
Esempio n. 6
0
// Get server's request region STAG. Exchange queue pair attributes.
void client_exch_dest(struct ctrl_blk *cb)
{
	int sockfd, i, sock_port;

	struct sockaddr_in serv_addr;
	struct hostent *server;
	char server_name[20],sock_port_str[20];

	for(i = 0; i < NUM_SERVERS; i++) {
		// Find the server name and port from the "servers" file
		scanf("%s", server_name);
		scanf("%s", sock_port_str);
		printf("At client %d, server_name = %s, port = %s\n", cb->id, 
			server_name, sock_port_str);
		sock_port = atoi(sock_port_str);

		sockfd = socket(AF_INET, SOCK_STREAM, 0);
		CPE(sockfd < 0, "Error opening socket", 0);
	
		server = gethostbyname(server_name);
		CPE(server == NULL, "No such host", 0);
	
		bzero((char *) &serv_addr, sizeof(serv_addr));
		serv_addr.sin_family = AF_INET;
		bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
			server->h_length);
		serv_addr.sin_port = htons(sock_port);
	
		if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
			fprintf(stderr, "ERROR connecting\n");
		}

		// Get STAG
		if(read(sockfd, &server_req_area_stag[i], S_STG) < 0) {
			fprintf(stderr, "ERROR reading stag from socket\n");
		}
		fprintf(stderr, "Client %d <-- Server %d's stag: ", cb->id, i);
		print_stag(server_req_area_stag[i]);
	
		// Exchange attributes for connected QPs
		if(write(sockfd, &cb->local_conn_qp_attrs[i], S_QPA) < 0) {
			fprintf(stderr, "ERROR writing conn qp_attr to socket\n");
		}
		fprintf(stderr, "Client %d --> Server %d conn qp_attr: ", cb->id, i);
		print_qp_attr(cb->local_conn_qp_attrs[i]);

		if(read(sockfd, &cb->remote_conn_qp_attrs[i], S_QPA) < 0) {
			fprintf(stderr, "Error reading conn qp_attr from socket");
		}
		fprintf(stderr, "Client %d <-- Server %d's conn qp_attr: ", cb->id, i);
		print_qp_attr(cb->remote_conn_qp_attrs[i]);
		
		// Send datagram QP attrs. Clients don't need server's UD QP attrs
		// The client sends a different UD QP to each server
		if(write(sockfd, &cb->local_dgram_qp_attrs[i], S_QPA) < 0) {
			fprintf(stderr, "ERROR writing dgram qp_attr to socket\n");
		}
		fprintf(stderr, "Client %d --> Server %d UD qp_attr: ", cb->id, i);
		print_qp_attr(cb->local_dgram_qp_attrs[i]);

		close(sockfd);
	}
}
Esempio n. 7
0
void *run_server(void *arg)
{
	int i;
	int ud_qp_i = 0;	/* UD QP index */
	struct thread_params params = *(struct thread_params *) arg;
	int srv_gid = params.id;	/* Global ID of this server thread */
	int ib_port_index = params.dual_port == 0 ? 0 : srv_gid % 2;

	struct hrd_ctrl_blk *cb = hrd_ctrl_blk_init(srv_gid,	/* local_hid */
		ib_port_index, -1, /* port_index, numa_node_id */
		0, 0,	/* conn qps, use uc */
		NULL, 0, -1,	/* prealloc conn buf, conn buf size, key */
		NUM_UD_QPS, BUF_SIZE, -1);	/* num_dgram_qps, dgram_buf_size, key */

	/* Buffer to receive requests into */
	memset((void *) cb->dgram_buf, 0, BUF_SIZE);

	for(ud_qp_i = 0; ud_qp_i < NUM_UD_QPS; ud_qp_i++) {
		/* Fill this QP with recvs before publishing it to clients */
		for(i = 0; i < HRD_Q_DEPTH; i++) {
			hrd_post_dgram_recv(cb->dgram_qp[ud_qp_i],
				(void *) cb->dgram_buf, params.size + 40,	/* Space for GRH */
				cb->dgram_buf_mr->lkey);
		}

		char srv_name[HRD_QP_NAME_SIZE];
		sprintf(srv_name, "server-%d-%d", srv_gid, ud_qp_i);

		hrd_publish_dgram_qp(cb, ud_qp_i, srv_name);
	}
	ud_qp_i = 0;

	printf("server: Server %d published QPs. Now polling..\n", srv_gid);

	struct ibv_recv_wr recv_wr[MAX_POSTLIST], *bad_recv_wr;
	struct ibv_wc wc[MAX_POSTLIST];
	struct ibv_sge sgl[MAX_POSTLIST];
	long long rolling_iter = 0;	/* For throughput measurement */
	int w_i = 0;	/* Window index */
	int ret;

	struct timespec start, end;
	clock_gettime(CLOCK_REALTIME, &start);

	int recv_offset = 0;
	while(recv_offset < params.size + 40) {
		recv_offset += CACHELINE_SIZE;
	}
	assert(recv_offset * params.postlist <= BUF_SIZE);

	while(1) {
		if(rolling_iter >= M_8) {
			clock_gettime(CLOCK_REALTIME, &end);
			double seconds = (end.tv_sec - start.tv_sec) + 
				(double) (end.tv_nsec - start.tv_nsec) / 1000000000;
			printf("main: Server %d: %.2f Mops. \n",
				srv_gid, rolling_iter / seconds);

			params.tput[srv_gid] = rolling_iter / seconds;
			if(srv_gid == 0) {
				double total_tput = 0;
				for(i = 0; i < NUM_SERVER_THREADS; i++) {
					total_tput += params.tput[i];
				}
				hrd_red_printf("main: Total tput %.2f Mops.\n", total_tput);
			}
			
			rolling_iter = 0;
		
			clock_gettime(CLOCK_REALTIME, &start);
		}

		int num_comps = ibv_poll_cq(cb->dgram_recv_cq[ud_qp_i],
			params.postlist, wc);
		if(num_comps == 0) {
			continue;
		}

		/* Post a batch of RECVs */
		for(w_i = 0; w_i < num_comps; w_i++) {
			assert(wc[w_i].imm_data == 3185);
			sgl[w_i].length = params.size + 40;
			sgl[w_i].lkey = cb->dgram_buf_mr->lkey;
			sgl[w_i].addr = (uintptr_t) &cb->dgram_buf[0];

			recv_wr[w_i].sg_list = &sgl[w_i];
			recv_wr[w_i].num_sge = 1;
			recv_wr[w_i].next = (w_i == num_comps - 1) ?
				NULL : &recv_wr[w_i + 1];
		}

		ret = ibv_post_recv(cb->dgram_qp[ud_qp_i], &recv_wr[0], &bad_recv_wr);
		CPE(ret, "ibv_post_recv error", ret);

		rolling_iter += num_comps;
		HRD_MOD_ADD(ud_qp_i, NUM_UD_QPS);

	}

	return NULL;
}