EssayGhost Assignment代写,Essay代写,网课代修,Quiz代考

EssayGhost-Essay代写,作业代写,网课代修代上,cs代写代考

一站式网课代修,论文代写

高质量的Assignment代写、Paper代写、Report代写服务

EG1hao
网课代修代上,cs代写代考
C/C++代写
您的位置: 主页 > 编程案例 > C/C++代写 >
代写C++/C:代写CS之C语言-CPSC 213 – Assignment 9 IO, Asynchrony and Threads - C++代写
发布时间:2021-07-25 22:27:22浏览次数:
After a 24-hour grace period, late assignments will only be accepted in extenuating circumstances with documentation.The goal of this assignment is to examine asynchronous programming and threads. You are given a C file that models a simplified disk with asynchronous read operations, simulated DMA, and interrupts. You are also given four programs that perform a sequence of disk reads in different ways. The first of these programs is completely implemented. It access the disk sequentially, waiting for each request to finish before moving on. The next two programs are partly implemented, with the rest left to you. The first improves on the sequential version using asynchronous, event-driven programming. You will gain some experience with this style of programming and then compare the runtime performance of the two alternatives. The second uses threads to turn the asynchronous operations into synchronous ones, allowing you to write code like the synchronous program and get performance like the asynchronous one. The final program goes back to the asynchronous model for a more interesting challenge.BackgroundThe Simulated DiskThe simulated disk is implemented in the file disk.cand its public interface is in disk.h. You can completely ignore the implementation; you’ll just use it.Recall that a disk contains a collection of blocks named by a block number. Programs running on the CPU request disk blocks (usually 4-KB or so at a time) using a combination of PIO, DMA and interrupts. They use PIO to tell the disk controller which blocks they want and where in memory they want the disk to place the data (i.e., the content of the blocks). The disk controller uses DMA to transfer this data into memory and then sends an interrupt to the CPU to inform it that the transfer has completed. The total elapsed time for this operation is referred to as the latency of theread.Our simulated disk models a fixed, per-access read latency of 10 ms (1 ms is 10-3 seconds), which is about the average access time of real disks. This means that it takes the disk 10 ms to process a single read request. However, the disk can process multiple requests in parallel.When it completes a request, it does what a real disk does, it uses a direct-memory transfer (DMA) to copy the disk data into main memory and it delivers an interrupt to the CPU. In this case, of course, the DMA is just a memory-to-memory copy between parts of your program’s memory. And the interrupt is delivered by calling a specified handling procedure you register when you initialize the disk.To initialize the disk to use an interrupt handler called interrupt_service_routine, you call the following procedure at the beginning of your program (all of the provided files already do this).disk_start (interrupt_service_routine);To request that the content of the disk block numbered blocknobe transferred memory at the address stored in result, you do this.disk_schedule_read (result, blockno);This procedure returns immediately. Then 10ms later, the target data is copied into memory at the address in result and an interrupted is delivered to you by calling interrupt_service_routine. The disk completes reads in request order, and calls interrupt_service_routinefor each completion.Like a real disk, multiple calls to disk_schedule_readwill be handled in parallel; this fact is helpful to know when comparing the performance of the different versions of the read programs you will be modifying and running.Unlike a real disk, each block of this disk is just an integer. So, for example to schedule a read of the value of block 1234into the variable result, you could do something like this.int result;disk_schedule_read ( result, 1234);But, be careful, because this read will happen later and so be sure that (a) resultisn’t a local variable that is deallocated before the read completes and (b) if you have multiple outstanding disk reads, they don’t all use the same resultvariable.Note — and this is important — the interrupt operates just like a real interrupt. It will interrupt your program at some arbitrary point to run your interrupt service routine (isr) and then continue, your program when the isr completes. There are some potentially difficult (and I truly mean horrible) issues that arise if your program and the isr access any data structures in common or if the isr calls any non-reentrant procedure (e.g., malloc or free). You are provided with the implementation of a reentrant, thread-safe queue that is safe to access from the handler and your program. It is also okay to access the target data buffer (buf)in the handler. Do not access anyother data structures in the handler and do not call freefrom the handler (its okay to calldequeue).The QueueThe files queue.cand queue.hprovide you with a thread-safe, re-entrant implementation of a queue. If you need to enqueue information in your program that is dequeued in the interrupt handler, use this queue.To create a queue named something like prq, for example, you declare the variable like this.queue_t prq;Then before you use the queue you need to initialize it, in main, for example like this.prq = queue_create();To add an the tuple (val, arg, callback) to the queue do this (note that arg isn’t needed until the last question, so you an use NULL for this parameter in the meantime).queue_enqueue (prq, val, arg, callback);To get a tuple from the queue, declare variables to store the results and then pass them by reference to dequeue:void *val, *arg;void (*callback) (void*,void*); queue_dequeue (prq, val, arg, callback);Or if you aren’t using arg: void *val;void (*callback) (void*,void*); queue_dequeue (prq, val, NULL, callback);Timing the Execution of a ProgramThe UNIX command time can be prepended to any command to time its execution. When the command finishes you get a report of three times: the total elapsed clock time, the time spent in user-mode (i.e., your program code) and the time spent system-mode (i.e., the operating system). The format is otherwise a bit different on different platforms.For example if you type this:time ./sRead 100You will get something like this on Mac OS when sReadcompletes:1.074u 0.010s0:01.08100.0% 0+0k 0+0io0pf+0wAnd on Linux:real 0m1.100s user 0m1.084s sys0m0.000sIgnore the user (u) and sys (s) times; they really are approximations. Pay attention only to the real, elapsed time, which is 1.08 s in the Mac example and 1.1 s in the Linux example.You will use this command to assess and compare the runtime performance of the three alternative programs.Hints: Creating and Joining with Threads in RunYou should create a separate thread for each call to readusing:uthread_create (void* (*start_proc)(void*), void* start_arg)Also note that it is necessary to joint with a thread (i.e, uthread_join(t)) if you want to wait until the thread completes. You will need to do this in run, because when main returns the program will terminate, even if there are other threads running.Hints: Blocking and Unblocking ThreadsA thread can block itself at any time by calling uthread_block. Another thread can wakeup a blocked thread (t) by calling uthread_unblock(t). Recall that you will need to block threads after they call disk_scheduleRead and before they call handleRead. And that this blocked thread should be awoken when the disk read on which it is waiting has completed. Also recall that a thread can obtain its own identity (e.g., for unblocking) by calling uthread_self().What toDoDownload the Provided CodeThe file www.ugrad.cs.ubc.ca/~cs213/cur/assignments/a9/code.zip contains the code files you will use for this assignment this includes the implementation of uthreads, spinlocks, a simulated disk, and other files used in each of the questions below.Question 1: Synchronous Disk Read by Wasting CPU TimeExamine the program sRead.c, compile it by typing make sReadand run it.You run it from the command line with one argument, the number of reads to perform. For example, to perform 100 reads, you type this:./sRead 100You might want to add some printf’s to get a better idea of what is happening. Be sure that you understand what is_read_pending is and how it is used. Before moving to the next step be sure that you remove any printf’s that you added.Finally, time the execution of the program for executions that read various numbers of blocks.For exampletime ./sRead 10time ./sRead 100time ./sRead 1000Knowing how the simulated disk and this program perform you should be able to explain why you see the runtime performance you do.Record your data, observations, and explanation in the file Q1.txt.Question 2: Implement Asynchronous Read — aRead.cStep 1Open aRead.c in an editor and examine it carefully. This version of the read program will use event-driven style programming to handle the disk reads asynchronously. That is, each read request registers a completion routine and returns immediately. The completion routines are then called by the disk interrupt service routine when each read completes.The interrupt_service_routine and some other code is provided. You must implement the handle_readprocedure and the code that schedules the reads in main. Note that there is an infinite loop at the end of main. This is needed because the program will terminate when main returns even if there are some reads that haven’t completed. And, of course, NONE of them will have completed since all that will have happened by the time you reach the end of main is that you will have scheduled all of the reads; none of them will have completed yet. The program will terminate when exit() is called, as you can see in handle_read_and_exit.Compile and test your program and be sure that it produces the same output as sRead.Step 2To get a better understanding of how the interrupt interleaves with your program, run your programming in the debugger and set a breakpoint in interrupt_service_routine. When it stops, print out a stack trace. You will see something like this, for example.*frame #0: 0x00000001000007db aRead`interrupt_service_routine ataRead.c:23 frame #1: 0x0000000100000d58 aRead`deliverInterrupt atdisk.c:105frame #2: 0x0000000100000e1a aRead`handleTimerInterrupt(signo=14, info=0x00007ffeefbff620,uap=0x00007ffeefbff688) at disk.c:118 frame #3: 0x00007fff76328f5a libsystem_platform.dylib`_sigtramp +26frame #4: 0x0000000100000a00 aRead`main(argc=2, argv=0x00007ffeefbff7d8) ataRead.c:65 frame #5: 0x00007fff760a7115 libdyld.dylib`start +1frame #6: 0x00007fff760a7115 libdyld.dylib`start +1Look at activation frame #4 in this example (your stack trace will be a bit different). It shows the program running at aRead.cat line 65, which is the infinite while loop at the end of main.Frame #3 is the “interrupt” (actually a timer signal delivered by the operating system to disk.c, which is how we simulate interrupts). Frames #2 and #1 are code in the simulated disk that handle this interrupt and translate it into a call your isr, which is the top frame, stopped at the breakpoint.Step 3Now, measure the runtime performance of aReadfor executions that read different numbers of disk blocks as you did with sReadand so that you can directly compare their performance.There is some experimental error and so you should run each case at least three times and take the minimum. The reason for taking the minimum is that this is the most reliable way to factor out extraneous events that you see as noise in your numbers. Obviously, this is not a good way to determine the expected behaviour of the programs; its just a good way to compare them.Now you know more and have more data. Record the timevalues you observe for both aRead and sRead for a few different numbers of reads. Be sure to choose meaningful values for this parameter; e.g., at least a small one of around 10 and a large one of around 1000 (though if your system is too slow to run either of these for 1000, choose a smaller number). Explain what you observe: both what and why. The why part is important: carefully explain why one of these is faster than the other.Record your data, observations, and explanation in the file Q2.txt.Question 3: Using Threads to Hide AsynchronyNow open the new file tRead.c in an editor and examine it carefully. The goal in this new version is to read and handle disk blocks sequentially in a manner similar to sReadbut to do so using threads to get performance similar to aRead.To do this, it will be necessary to create multiple threads so that threads can stop to wait for disk reads to complete without the negative performance consequences seen in sRead.c.See the Background section above for some notes that help with the implementation. This time you must implement the interrupt_service_routineyourself.Compile and test your program.Evaluate this version as you did the other two. Compare their performance and record your data. Compare both the elapsed time (as you have previous) and the system time of aRead and tRead, which measures the approximate amount of time the program spends running in the operating system. If there is a significant difference note it.Record your data, observations, and explanation in the file Q3.txt.Question 4: More Fun with Asynchronous ProgrammingIn this final step you will implement a program that goes on a treasure hunt through the disk.The program’s command-line argument is the block number where the hunt will start. In the first step of the hunt, you must read the value of this block. This value will tell you two things: (1) the number of additional steps to perform and (2) the address of the next block to read. In each subsequent step the block value that is read gives you the block number of the next block to read. Print out the value of the last block youread.For example if you type this./treasureHunt 21You should read block 21 first. Lets assume that the value of block 21 is 7. If so, you should read 7 more blocks, starting with block number 7. If the value of block 7 is 12, then that is the third block you read, an so on. Note that in total you will have read 8 blocks.The code pack includes the starter file for treasureHunt.c. Work incrementally. You can use aRead as a guide to get started. A good first step would be to read the value of the initial block and print it. Then a good second step would be to read the second block and print its value. Now think about adding the counter argument to the callback (that’s what argis for) and counting down. Finally, be sure that you only print the value of the last block and that your program terminates when itsdone.What to Hand InUse the handinprogram.The assignment directory is ~/cs213/a9, it should contain the following plain-text files.1.README.txtthat contains the name and student number of you and your partner2.PARTNER.txtcontaining your partner’s CS login id and nothing else (i.e., the 4- or 5-digit id in the form a0z1). Your partner should not submitanything.3.For Question 1:Q1.txt.4.For Question 2: aRead.cand Q2.txt.5.For Question 3: tRead.cand Q3.txt.6.For Question 4:treasureHunt.c.代写CS Finance|建模|代码|系统|报告|考试编程类:C++,JAVA ,数据库,WEB,Linux,Nodejs,JSP,Html,Prolog,Python,Haskell,hadoop算法,系统 机器学习金融类:统计,计量,风险投资,金融工程,R语言,Python语言,Matlab,建立模型,数据分析,数据处理服务类:Lab/Assignment/Project/Course/Qzui/Midterm/Final/Exam/Test帮助代写代考辅导天才写手,代写C,代写R,代写JAVA,考试助攻E-mail:[email protected]微信:BadGeniuscs 工作时间:无休息工作日-早上8点到凌晨3点如果您用的手机请先保存二维码到手机里面,识别图中二维码。如果用电脑,直接掏出手机果断扫描。

所有的编程代写范围:essayghost为美国、加拿大、英国、澳洲的留学生提供C语言代写、代写C语言、C语言代做、代做C语言、数据库代写、代写数据库、数据库代做、代做数据库、Web作业代写、代写Web作业、Web作业代做、代做Web作业、Java代写、代写Java、Java代做、代做Java、Python代写、代写Python、Python代做、代做Python、C/C++代写、代写C/C++、C/C++代做、代做C/C++、数据结构代写、代写数据结构、数据结构代做、代做数据结构等留学生编程作业代写服务。