/*-------------------------------------------------------------------------* * 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; }
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; }
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; }
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; }
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; }
// 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); } }
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; }