cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
mceuropeanengine_host.cpp
Go to the documentation of this file.
1 
17 
33 #include <stdio.h>
34 #include <iostream> // For cout and cerr
35 #include <cstdlib> // For atoi()
36 #include <assert.h> // For assert()
37 #include <string> // For to_string
38 #include <string.h>
39 #include <arpa/inet.h>
40 
41 #include "../../../../../PracticalSockets/src/PracticalSockets.h" // For UDPSocket and SocketException
42 #include "../include/config.h"
43 
44 using namespace std;
45 
46 
47 void delay(unsigned int mseconds)
48 {
49  clock_t goal = mseconds + clock();
50  while (goal > clock());
51 }
52 
53 
54 void print_cFpZoo(void)
55 {
56  cout << " " << endl;
57  cout << "...build with: " << endl;
58  cout << " ██████╗███████╗██████╗ ███████╗ ██████╗ ██████╗ " << endl;
59  cout << "██╔════╝██╔════╝██╔══██╗ ╚══███╔╝██╔═══██╗██╔═══██╗ " << endl;
60  cout << "██║ █████╗ ██████╔╝ ███╔╝ ██║ ██║██║ ██║ " << endl;
61  cout << "██║ ██╔══╝ ██╔═══╝ ███╔╝ ██║ ██║██║ ██║ " << endl;
62  cout << "╚██████╗██║ ██║███████╗███████╗╚██████╔╝╚██████╔╝ " << endl;
63  cout << " ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝ " << endl;
64  cout << "A cloudFPGA project from IBM ZRL v1.0 " << endl;
65  cout << "Quantitative Finance Monte-Carlo European Pricing Engine " << endl;
66 }
67 
68 #ifdef PY_WRAP
69 void mceuropeanengine(DtUsedInt loop_nm, DtUsed *outarg, char *s_servAddress, char *s_servPort,
76  DtUsed strike,
82 {
83 #else
88 int main(int argc, char *argv[])
89 {
90  if ((argc < 3) || (argc > 4)) { // Test for correct number of arguments
91  cerr << "Usage: " << argv[0] << " <Server> <Server Port> \n";
92  exit(1);
93  }
94 #endif
95 
96 
97  //------------------------------------------------------
98  //-- STEP-1 : Socket and variables definition
99  //------------------------------------------------------
100 
101  #ifndef PY_WRAP
102  assert (argc == 3);
103  string s_servAddress = argv[1]; // First arg: server address
104  char *s_servPort = argv[2];
105  #endif
106 
107  string servAddress = s_servAddress;
108  unsigned short servPort;
109  bool net_type = NET_TYPE;
110  if (net_type == udp) {
111  servPort = Socket::resolveService(s_servPort, "udp");
112  }
113  else if (net_type == tcp) {
114  servPort = atoi(s_servPort);
115  }
116  else {
117  cout << "ERROR: Invalid type of socket type provided: " << net_type << " Choosed one of (tcp=0 or udp=1)" << endl;
118  }
119 
120  if ((servPort <= 0) || (servPort <= 1024) || (servPort >= 65536)) {
121  cerr << "ERROR: Invalid port number " << servPort <<
122  ". Please select a value at range [1025-65535]. Aborting..." << endl;
123  exit(1);
124  }
125 
126  char buffer[BUF_LEN]; // Buffer for echo string
127  unsigned int recvMsgSize; // Size of received message
128  unsigned int num_frame = 0;
129  std::string input_string;
130  //UDPSocket *udpsock_p;
131  //TCPSocket *tcpsock_p;
132 
133  print_cFpZoo();
134 
135  try {
136 
137  //------------------------------------------------------
138  //-- STEP-2 : Initialize socket connection
139  //------------------------------------------------------
140  #if (NET_TYPE == udp)
141  #ifndef TB_SIM_CFP_VITIS
142  UDPSocket udpsock(servPort); // NOTE: It is very important to set port here in order to call
143  // bind() in the UDPSocket constructor
144  #else // TB_SIM_CFP_VITIS
145  UDPSocket udpsock; // NOTE: In HOST TB the port is already binded by mceuropeanengine_host_fwd_tb.cpp
146  #endif // TB_SIM_CFP_VITIS
147  //udpsock_p = &udpsock;
148  #else // tcp
149  TCPSocket tcpsock(servAddress, servPort);
150  //tcpsock_p = &tcpsock;
151  #endif // udp/tcp
152 
153  //------------------------------------------------------------------------------------
154  //-- STEP-3 : Create an input struct
155  //------------------------------------------------------------------------------------
156  varin instruct;
157  #ifndef PY_WRAP
158  instruct.loop_nm = OUTDEP;
159  instruct.timeSteps = 1;
160  instruct.requiredTolerance = 0.02f;
161  instruct.underlying = 36;
162  instruct.riskFreeRate = 0.06;
163  instruct.volatility = 0.20;
164  instruct.dividendYield = 0.0;
165  instruct.strike = 40;
166  instruct.optionType = 1;
167  instruct.timeLength = 1;
168  instruct.seed = 4332 ; // 441242, 42, 13342;
169  instruct.requiredSamples = 1; // 262144; // 48128;//0;//1024;//0;
170  instruct.maxSamples = 1;
171  #else
172  instruct.loop_nm = loop_nm;
173  instruct.timeSteps = timeSteps;
175  instruct.underlying = underlying;
176  instruct.riskFreeRate = riskFreeRate;
177  instruct.volatility = volatility;
178  instruct.dividendYield = dividendYield;
179  instruct.strike = strike;
180  instruct.optionType = optionType;
181  instruct.timeLength = timeLength;
182  instruct.seed = seed;
183  instruct.requiredSamples = requiredSamples;
184  instruct.maxSamples = maxSamples;
185  #endif
186 
187  assert(instruct.loop_nm > 0);
188  assert(instruct.loop_nm <= OUTDEP);
189 
190  clock_t start_cycle_main = clock();
191  cout << " ___________________________________________________________________ " << endl;
192  cout << "/ \\" << endl;
193  cout << "INFO: Batch # " << ++num_frame << endl;
194 
195  // Ensure that the selection of MTU is a multiple of 8 (Bytes per transaction)
196  assert(PACK_SIZE % 8 == 0);
197 
198  unsigned int total_pack_tx = 1 + (sizeof(instruct) - 1) / PACK_SIZE;
199  unsigned int total_pack_rx = 1 + (instruct.loop_nm*sizeof(DtUsed) - 1) / PACK_SIZE;
200  unsigned int total_bytes = total_pack_tx * PACK_SIZE;
201  unsigned int bytes_in_last_pack_tx = sizeof(instruct) - (total_pack_tx - 1) * PACK_SIZE;
202  unsigned int bytes_in_last_pack_rx = instruct.loop_nm*sizeof(DtUsed) - (total_pack_rx - 1) * PACK_SIZE;
203 
204  cout << "INFO: Network socket : " << ((net_type == tcp) ? "TCP" : "UDP") << endl;
205  cout << "INFO: Total packets to send : " << total_pack_tx << endl;
206  cout << "INFO: Total packets to receive : " << total_pack_rx << endl;
207  cout << "INFO: Total bytes to send : " << sizeof(instruct) << endl;
208  cout << "INFO: Total bytes to receive : " << instruct.loop_nm*sizeof(DtUsed) << endl;
209  cout << "INFO: Total bytes in " << total_pack_tx << " packets : " << total_bytes << endl;
210  cout << "INFO: Bytes in last packet send: " << bytes_in_last_pack_tx << endl;
211  cout << "INFO: Bytes in last packet recv: " << bytes_in_last_pack_rx << endl;
212  cout << "INFO: Packet size (custom MTU) : " << PACK_SIZE << endl;
213 
214  //------------------------------------------------------
215  //-- STEP-4 : RUN mceuropeanengine FROM cF (HW)
216  //------------------------------------------------------
217  clock_t start_cycle_mceuropeanengine_hw = clock();
218 
219  //------------------------------------------------------
220  //-- STEP-5.1 : TX Loop
221  //------------------------------------------------------
222  clock_t last_cycle_tx = clock();
223  unsigned int sending_now = PACK_SIZE;
224  for (unsigned int i = 0; i < total_pack_tx; i++) {
225  if ( i == total_pack_tx - 1 ) {
226  sending_now = bytes_in_last_pack_tx;
227  }
228  #if (NET_TYPE == udp)
229  udpsock.sendTo( & instruct, sending_now, servAddress, servPort);
230  #else
231  tcpsock.send( & instruct, sending_now);
232  #endif
233  delay(1000);
234  }
235 
236  clock_t next_cycle_tx = clock();
237  double duration_tx = (next_cycle_tx - last_cycle_tx) / (double) CLOCKS_PER_SEC;
238  cout << "INFO: Effective SPS TX:" << (1 / duration_tx) << " \tkbps:" << (PACK_SIZE *
239  total_pack_tx / duration_tx / 1024 * 8) << endl;
240  last_cycle_tx = next_cycle_tx;
241 
242 
243  //------------------------------------------------------
244  //-- STEP-5.2 : RX Loop
245  //------------------------------------------------------
246  clock_t last_cycle_rx = clock();
247  unsigned int receiving_now = PACK_SIZE;
248  cout << "INFO: Expecting length of packs:" << total_pack_rx << endl;
249  char * longbuf = new char[PACK_SIZE * total_pack_rx];
250  memset(longbuf, 0, PACK_SIZE * total_pack_rx);
251  for (unsigned int i = 0; i < instruct.loop_nm*sizeof(DtUsed); ) {
252  //cout << "DEBUG: " << i << endl;
253  if ( i == total_pack_rx - 1 ) {
254  receiving_now = bytes_in_last_pack_rx;
255  }
256  #if (NET_TYPE == udp)
257  recvMsgSize = udpsock.recvFrom(buffer, BUF_LEN, servAddress, servPort);
258  #else
259  recvMsgSize = tcpsock.recv(buffer, BUF_LEN);
260  #endif
261  memcpy( & longbuf[i], buffer, recvMsgSize);
262  i += recvMsgSize;
263  if (recvMsgSize != receiving_now) {
264  cerr << "WARNING: Received unexpected size pack:" << recvMsgSize << ". Expected: " <<
265  receiving_now + " . Breaking Rx..."<< endl;
266  break;
267  }
268  //cout << "DEBUG: recvMsgSize=" << recvMsgSize << endl;
269  }
270 
271  cout << "INFO: Received packet from " << servAddress << ":" << servPort << endl;
272  #ifndef PY_WRAP
273  DtUsed *out = (DtUsed*)malloc(instruct.loop_nm*sizeof(DtUsed));
274  #else
275  DtUsed *out = outarg;
276  #endif
277 
278  for (unsigned int i = 0, j = 0; i < instruct.loop_nm; i++, j+=sizeof(DtUsed)) {
279  memcpy(&out[i], &longbuf[j], sizeof(DtUsed));
280  }
281 
282  cout << "INFO: Received option price vector: " << endl;
283  for (unsigned int i = 0; i < instruct.loop_nm; i++) {
284  cout << i<< " : " << out[i] << endl;
285  }
286 
287  clock_t next_cycle_rx = clock();
288  double duration_rx = (next_cycle_rx - last_cycle_rx) / (double) CLOCKS_PER_SEC;
289  cout << "INFO: Effective SPS RX:" << (1 / duration_rx) << " \tkbps:" << (PACK_SIZE *
290  total_pack_rx / duration_rx / 1024 * 8) << endl;
291  last_cycle_rx = next_cycle_rx;
292 
293  clock_t end_cycle_mceuropeanengine_hw = next_cycle_rx;
294 
295  double duration_mceuropeanengine_hw = (end_cycle_mceuropeanengine_hw - start_cycle_mceuropeanengine_hw) /
296  (double) CLOCKS_PER_SEC;
297  cout << "INFO: HW exec. time:" << duration_mceuropeanengine_hw << " seconds" << endl;
298  cout << "INFO: Effective SPS HW:" << (1 / duration_mceuropeanengine_hw) << " \tkbps:" <<
299  (PACK_SIZE * (total_pack_rx + total_pack_rx) / duration_mceuropeanengine_hw / 1024 * 8) << endl;
300 
301  double duration_main = (clock() - start_cycle_main) / (double) CLOCKS_PER_SEC;
302  #ifndef PY_WRAP
303  free(out);
304  #endif
305  cout << "INFO: Effective SPS E2E:" << (1 / duration_main) << endl;
306  cout << "\\___________________________________________________________________/" << endl
307  << endl;
308 
309  // Destructor closes the socket
310  } catch (SocketException & e) {
311  cerr << e.what() << endl;
312  exit(1);
313  }
314  #ifndef PY_WRAP
315  return 0;
316  #endif
317 }
318 
319 
320 
321 
cat GET request dos socat stdio tcp
Definition: commands.txt:1
void mceuropeanengine(ap_uint< 32 > *pi_rank, ap_uint< 32 > *pi_size, stream< NetworkWord > &siSHL_This_Data, stream< NetworkWord > &soTHIS_Shl_Data, stream< NetworkMetaStream > &siNrc_meta, stream< NetworkMetaStream > &soNrc_meta, ap_uint< 32 > *po_rx_ports)
Main process of the MCEuropeanEngine Application directives.
int main(int argc, char *argv[])
void print_cFpZoo(void)
long unsigned int DtUsedInt
Definition: config.h:74
#define OUTDEP
Definition: config.h:63
void delay(unsigned int mseconds)
#define DtUsed
Definition: config.h:57
#define udp
Definition: config.h:66
#define NET_TYPE
Definition: config.h:60
#define BUF_LEN
Definition: config.h:54
#define PACK_SIZE
Definition: config.h:51
int timeSteps
Definition: test.py:37
int requiredSamples
Definition: test.py:36
float volatility
Definition: test.py:29
int optionType
Definition: test.py:34
int seed
Definition: test.py:27
float strike
Definition: test.py:33
int timeLength
Definition: test.py:32
float requiredTolerance
Definition: test.py:35
float underlying
Definition: test.py:28
int maxSamples
Definition: test.py:38
float riskFreeRate
Definition: test.py:31
out
Definition: test.py:12
float dividendYield
Definition: test.py:30
int loop_nm
Definition: test.py:26
def clock()
Definition: common.py:174
Definition: config.h:85
double dividendYield
Definition: config.h:90
DtUsedInt seed
Definition: config.h:87
DtUsedInt maxSamples
Definition: config.h:98
double riskFreeRate
Definition: config.h:91
double volatility
Definition: config.h:89
double requiredTolerance
Definition: config.h:95
DtUsedInt loop_nm
Definition: config.h:86
double underlying
Definition: config.h:88
DtUsedInt timeSteps
Definition: config.h:97
double strike
Definition: config.h:93
DtUsedInt requiredSamples
Definition: config.h:96
DtUsedInt optionType
Definition: config.h:94
double timeLength
Definition: config.h:92