1 00:00:00,120 --> 00:00:02,500 The following content is provided under a Creative 2 00:00:02,500 --> 00:00:03,910 Commons license. 3 00:00:03,910 --> 00:00:06,950 Your support will help MIT OpenCourseWare continue to 4 00:00:06,950 --> 00:00:10,600 offer high quality educational resources for free. 5 00:00:10,600 --> 00:00:13,500 To make a donation or view additional materials from 6 00:00:13,500 --> 00:00:17,430 hundreds of MIT courses, visit MIT OpenCourseWare at 7 00:00:17,430 --> 00:00:18,680 ocw.mit.edu. 8 00:00:29,540 --> 00:00:30,010 PROFESSOR: All right. 9 00:00:30,010 --> 00:00:32,759 Can everyone hear me? 10 00:00:32,759 --> 00:00:35,960 So I guess it's 2:35, and we might as well get started. 11 00:00:35,960 --> 00:00:39,110 So the calendar, I think, still says that we have a 12 00:00:39,110 --> 00:00:42,690 guest lecture today but sorry to disappoint you, there is no 13 00:00:42,690 --> 00:00:43,970 guest lecture. 14 00:00:43,970 --> 00:00:47,640 Instead we have a quiz for you on Thursday, which is 15 00:00:47,640 --> 00:00:48,950 so much more fun. 16 00:00:48,950 --> 00:00:50,560 Not really. 17 00:00:50,560 --> 00:00:53,950 But I do realize that everybody has a lot to do, 18 00:00:53,950 --> 00:00:55,300 even just for this class. 19 00:00:55,300 --> 00:00:57,300 You guys have your final project and so on. 20 00:00:57,300 --> 00:00:59,360 So hopefully this will be helpful. 21 00:00:59,360 --> 00:01:03,340 It won't take the entire 1 and 1/2 hours, I don't think. 22 00:01:03,340 --> 00:01:06,420 And the remaining time will be up in office hours, answering 23 00:01:06,420 --> 00:01:08,880 questions about stuff. 24 00:01:08,880 --> 00:01:15,020 So the first thing is I decided to run some stats that 25 00:01:15,020 --> 00:01:17,270 we haven't run before for this class. 26 00:01:17,270 --> 00:01:20,100 These are your Project 42 4.2 final submissions. 27 00:01:20,100 --> 00:01:23,840 And in the red are your beta submission run times. 28 00:01:23,840 --> 00:01:26,380 And in the blue are your corresponding final 29 00:01:26,380 --> 00:01:28,540 submission run times. 30 00:01:28,540 --> 00:01:31,820 I thought it was just interesting to see some groups 31 00:01:31,820 --> 00:01:36,590 did massive improvements, while others didn't really 32 00:01:36,590 --> 00:01:39,020 change their programs much. 33 00:01:39,020 --> 00:01:43,890 And just to give you an idea, a 90% for your performance 34 00:01:43,890 --> 00:01:48,090 grade is indicated by that green line and below. 35 00:01:48,090 --> 00:01:50,470 So the majority of the class did really well. 36 00:01:54,800 --> 00:01:55,240 All right. 37 00:01:55,240 --> 00:01:58,420 So the thing that everybody's concerned about. 38 00:01:58,420 --> 00:02:03,070 So Quiz 2 will be in lecture on Thursday. 39 00:02:03,070 --> 00:02:06,220 It'll be an 80 minute quiz, similar in format to the 40 00:02:06,220 --> 00:02:07,680 previous one. 41 00:02:07,680 --> 00:02:12,400 And you guys once again are allowed a one-page handwritten 42 00:02:12,400 --> 00:02:14,060 crib sheet. 43 00:02:14,060 --> 00:02:19,730 And it covers everything that has been done since Quiz 1. 44 00:02:19,730 --> 00:02:22,340 It's not designed to be cumulative, but unfortunately 45 00:02:22,340 --> 00:02:24,470 due to the nature of the class, there's going to be 46 00:02:24,470 --> 00:02:28,130 some things from the previous part of the class that you 47 00:02:28,130 --> 00:02:31,950 would need to know or it would be helpful to know. 48 00:02:31,950 --> 00:02:36,100 Unlike last time, we didn't post a practice quiz on 49 00:02:36,100 --> 00:02:39,410 Stellar, because it turns out that the material and the 50 00:02:39,410 --> 00:02:41,650 order of the material gets shuffled around quite a bit 51 00:02:41,650 --> 00:02:42,200 every year. 52 00:02:42,200 --> 00:02:43,970 And we have different focuses. 53 00:02:43,970 --> 00:02:46,720 So posting a practice quiz would actually be pretty mean, 54 00:02:46,720 --> 00:02:49,330 because it would cause you guys to study the 55 00:02:49,330 --> 00:02:51,690 wrong things instead. 56 00:02:51,690 --> 00:02:57,250 Instead I try to extract the most useful things from our 57 00:02:57,250 --> 00:02:59,730 discussions of what the quiz is going to be this time. 58 00:02:59,730 --> 00:03:03,010 So hopefully all this information is helpful. 59 00:03:03,010 --> 00:03:04,800 Feel free to interrupt me at any 60 00:03:04,800 --> 00:03:06,225 time if you have questions. 61 00:03:10,040 --> 00:03:13,790 So the first part, I would roughly call analyzing and 62 00:03:13,790 --> 00:03:16,680 possibly writing parallel programs. 63 00:03:16,680 --> 00:03:22,790 And to start off, is everybody familiar with what one of 64 00:03:22,790 --> 00:03:24,500 these graphs represents? 65 00:03:24,500 --> 00:03:27,600 So you have work and then each circle is a 66 00:03:27,600 --> 00:03:28,730 unit amount of work. 67 00:03:28,730 --> 00:03:32,460 And then the graph shows the dependencies of the things. 68 00:03:32,460 --> 00:03:35,400 So just to start off with a really simple question, what 69 00:03:35,400 --> 00:03:36,810 is the total amount of work represented? 70 00:03:41,779 --> 00:03:45,707 AUDIENCE: [LAUGHTER] 71 00:03:45,707 --> 00:03:46,198 PROFESSOR: Uh oh. 72 00:03:46,198 --> 00:03:49,798 I heard 17, which is not what I got when I counted this last 73 00:03:49,798 --> 00:03:50,617 night at 2:00. 74 00:03:50,617 --> 00:03:51,599 AUDIENCE: 26. 75 00:03:51,599 --> 00:03:52,849 AUDIENCE: 24. 76 00:03:55,050 --> 00:03:55,880 PROFESSOR: I like 24. 77 00:03:55,880 --> 00:03:57,750 AUDIENCE: [LAUGHTER] 78 00:03:57,750 --> 00:03:59,920 PROFESSOR: And I'm going to assume it's 24, and not 79 00:03:59,920 --> 00:04:02,980 embarrass myself by trying to count it. 80 00:04:02,980 --> 00:04:04,400 Now what is the span? 81 00:04:12,285 --> 00:04:14,265 AUDIENCE: 8. 82 00:04:14,265 --> 00:04:14,760 AUDIENCE: 8. 83 00:04:14,760 --> 00:04:15,750 AUDIENCE: 8. 84 00:04:15,750 --> 00:04:16,910 PROFESSOR: 8 sounds right. 85 00:04:16,910 --> 00:04:19,700 So the longest path-- there's actually a couple different 86 00:04:19,700 --> 00:04:23,710 paths that end up being 8, but I think 8's the right answer. 87 00:04:23,710 --> 00:04:25,982 So then parallelism? 88 00:04:25,982 --> 00:04:27,350 AUDIENCE: 3. 89 00:04:27,350 --> 00:04:28,870 PROFESSOR: Cool. 90 00:04:28,870 --> 00:04:30,760 All right. 91 00:04:30,760 --> 00:04:37,470 So now that we're done with that, how about a little bit 92 00:04:37,470 --> 00:04:39,300 of background on caches. 93 00:04:39,300 --> 00:04:46,500 So when you run programs in parallel, it causes some more 94 00:04:46,500 --> 00:04:49,450 interesting things to happen in cache that did not happen 95 00:04:49,450 --> 00:04:50,980 with serial execution. 96 00:04:50,980 --> 00:04:55,280 One of those things is true sharing-- 97 00:04:55,280 --> 00:04:58,330 cache misses-- which are caused when multiple 98 00:04:58,330 --> 00:05:01,920 processors, like multiple threads, are trying to operate 99 00:05:01,920 --> 00:05:04,250 on the same piece of data in memory. 100 00:05:04,250 --> 00:05:09,220 So as a result, your cache would be forced to synchronize 101 00:05:09,220 --> 00:05:11,300 that cache line and move it across-- 102 00:05:11,300 --> 00:05:13,730 copy it from the freshest processor to the other ones 103 00:05:13,730 --> 00:05:15,610 every time that it's requested. 104 00:05:15,610 --> 00:05:19,570 And you end up with a lot of overhead generated by 105 00:05:19,570 --> 00:05:21,580 continually doing these copies. 106 00:05:21,580 --> 00:05:24,660 So ideally you don't want to do this. 107 00:05:24,660 --> 00:05:28,380 But it's a lot easier said than done. 108 00:05:28,380 --> 00:05:31,850 False sharing is a little bit trickier because it's not 109 00:05:31,850 --> 00:05:34,930 immediately apparent from looking at your program that 110 00:05:34,930 --> 00:05:36,600 you're having multiple threads do the-- 111 00:05:36,600 --> 00:05:38,100 operate on the same data. 112 00:05:38,100 --> 00:05:40,940 Instead with false sharing, you have multiple processors 113 00:05:40,940 --> 00:05:45,080 that want to operate on different locations in memory. 114 00:05:45,080 --> 00:05:48,240 But due to the way that your computer's cache is organized, 115 00:05:48,240 --> 00:05:50,180 they just happen to be in the same cache line. 116 00:05:50,180 --> 00:05:55,080 As a result, you end up with the same memory, the same 117 00:05:55,080 --> 00:05:57,970 overhead, that you would see with true sharing. 118 00:05:57,970 --> 00:06:00,930 But when you look at the code itself, you don't think that 119 00:06:00,930 --> 00:06:04,430 you're doing anything that involves multiple threads 120 00:06:04,430 --> 00:06:07,620 operating on the same data. 121 00:06:07,620 --> 00:06:12,840 And so with that, here's a piece of code. 122 00:06:12,840 --> 00:06:17,910 And my question is this true sharing or false sharing? 123 00:06:17,910 --> 00:06:18,540 Let's take a vote. 124 00:06:18,540 --> 00:06:21,790 How many people think it's true sharing? 125 00:06:21,790 --> 00:06:22,770 Nobody. 126 00:06:22,770 --> 00:06:26,930 Well, how many people think it's false sharing? 127 00:06:26,930 --> 00:06:27,410 Come on. 128 00:06:27,410 --> 00:06:28,790 You have to vote one way or another. 129 00:06:31,850 --> 00:06:32,940 Let's try this again. 130 00:06:32,940 --> 00:06:35,650 True sharing? 131 00:06:35,650 --> 00:06:37,160 False sharing? 132 00:06:37,160 --> 00:06:38,060 That's better. 133 00:06:38,060 --> 00:06:40,440 All right, so it is indeed false sharing. 134 00:06:40,440 --> 00:06:43,350 And can someone propose a solution to fix it? 135 00:06:49,110 --> 00:06:49,530 Yes? 136 00:06:49,530 --> 00:06:51,878 AUDIENCE: Separate A and B, and put them 137 00:06:51,878 --> 00:06:55,260 in different shelves. 138 00:06:55,260 --> 00:06:56,350 PROFESSOR: Would that be sufficient? 139 00:06:56,350 --> 00:06:57,710 Putting them in different trucks? 140 00:07:00,530 --> 00:07:02,890 AUDIENCE: Then, padding the trucks. 141 00:07:02,890 --> 00:07:03,430 PROFESSOR: Yeah. 142 00:07:03,430 --> 00:07:04,630 Maybe with a little bit of padding, 143 00:07:04,630 --> 00:07:05,820 depending on your system. 144 00:07:05,820 --> 00:07:07,890 But sure, I'll accept that. 145 00:07:10,900 --> 00:07:14,140 But on the quiz, you might be asked to propose solutions to 146 00:07:14,140 --> 00:07:16,710 problems that you find. 147 00:07:16,710 --> 00:07:18,580 And hopefully those will be easier. 148 00:07:18,580 --> 00:07:20,830 Now on to a more fun topic-- 149 00:07:20,830 --> 00:07:21,710 synchronization. 150 00:07:21,710 --> 00:07:22,130 Yes? 151 00:07:22,130 --> 00:07:24,540 AUDIENCE: I have a question on sharing. 152 00:07:24,540 --> 00:07:28,396 So if two programs only access data, does that still count ? 153 00:07:33,230 --> 00:07:35,540 PROFESSOR: If you only access the data and nothing in the 154 00:07:35,540 --> 00:07:38,100 cache line is being modified, then you're safe, because 155 00:07:38,100 --> 00:07:40,690 every processor can independently read from their 156 00:07:40,690 --> 00:07:41,820 own copy of that. 157 00:07:41,820 --> 00:07:42,640 AUDIENCE: So that doesn't count. 158 00:07:42,640 --> 00:07:44,490 PROFESSOR: That doesn't count, correct. 159 00:07:44,490 --> 00:07:48,430 But the problem is if your cache line is 64 kilobytes, 160 00:07:48,430 --> 00:07:51,970 and any thread on any processor changes one piece of 161 00:07:51,970 --> 00:07:54,000 data inside that cache, then everybody 162 00:07:54,000 --> 00:07:55,250 has to pull new copies. 163 00:07:58,560 --> 00:08:02,760 So the classic example to demonstrate synchronization 164 00:08:02,760 --> 00:08:08,680 correctness is the dining philosophers problem, where 165 00:08:08,680 --> 00:08:10,880 you have n-- 166 00:08:10,880 --> 00:08:12,450 I believe five in this case-- 167 00:08:12,450 --> 00:08:16,050 philosophers, and five chopsticks. 168 00:08:16,050 --> 00:08:18,560 And each philosopher has to eat. 169 00:08:18,560 --> 00:08:22,210 So they use mutexes to-- 170 00:08:22,210 --> 00:08:25,040 well, generally you need-- 171 00:08:25,040 --> 00:08:29,070 each philosopher's code would be pick up two chopsticks and 172 00:08:29,070 --> 00:08:32,320 then eat and then put down their two chopsticks. 173 00:08:32,320 --> 00:08:36,039 It's somewhat of a contrived example, but it actually comes 174 00:08:36,039 --> 00:08:37,549 up in a lot of cases. 175 00:08:37,549 --> 00:08:41,630 And one of the cases where it comes up is in the system that 176 00:08:41,630 --> 00:08:45,480 I use to grade your unit tests. 177 00:08:45,480 --> 00:08:50,130 So I got impatient about running 200 or so 178 00:08:50,130 --> 00:08:51,420 unit test in series. 179 00:08:51,420 --> 00:08:55,450 And since I had about 200 cores altogether on the cloud 180 00:08:55,450 --> 00:08:58,010 machines, I figured, why not do them in parallel? 181 00:08:58,010 --> 00:09:00,860 But the problem is I need to run-- if I have students A and 182 00:09:00,860 --> 00:09:04,690 B, I need to run student A's test against student B's 183 00:09:04,690 --> 00:09:05,890 implementation. 184 00:09:05,890 --> 00:09:11,060 So the rough way that I did that was I grabbed a lock on 185 00:09:11,060 --> 00:09:14,000 student A's repository, grabbed a lock on student B's 186 00:09:14,000 --> 00:09:15,870 repository, and then modified-- 187 00:09:15,870 --> 00:09:19,370 swapped in their test files, did all my testing, and then 188 00:09:19,370 --> 00:09:22,060 returned the files to the original conditions, and then 189 00:09:22,060 --> 00:09:24,390 let go of the locks. 190 00:09:24,390 --> 00:09:26,720 Unfortunately, when you do that, you run into much of the 191 00:09:26,720 --> 00:09:29,980 same problem as the dining philosophers problems. 192 00:09:29,980 --> 00:09:36,310 So the naive strategy is for each philosopher, you grab a 193 00:09:36,310 --> 00:09:38,770 lock on your left chopstick. 194 00:09:38,770 --> 00:09:42,370 You grab a lock on your right one, with respect to you. 195 00:09:42,370 --> 00:09:47,590 And then you eat and then you unlock them in the same order. 196 00:09:47,590 --> 00:09:50,210 So this has a bug. 197 00:09:50,210 --> 00:09:51,850 Can anyone point out what it is? 198 00:09:54,694 --> 00:09:56,116 AUDIENCE: You want to unlock in a certain order. 199 00:09:58,970 --> 00:10:00,730 PROFESSOR: Actually, it doesn't matter which order you 200 00:10:00,730 --> 00:10:01,980 unlock in in in this case. 201 00:10:05,700 --> 00:10:09,230 So bad things happen if everybody starts at 202 00:10:09,230 --> 00:10:10,700 the exact same time. 203 00:10:10,700 --> 00:10:13,330 So everybody grabs their left chopstick. there's five 204 00:10:13,330 --> 00:10:15,320 people, five chopsticks, so that works fine. 205 00:10:15,320 --> 00:10:17,450 Now everybody wants to grab their right one, 206 00:10:17,450 --> 00:10:18,790 but it's not there. 207 00:10:18,790 --> 00:10:21,190 Because the person to the right already grabbed it as 208 00:10:21,190 --> 00:10:22,070 their left. 209 00:10:22,070 --> 00:10:26,620 So they wait forever for the right chopstick to appear and 210 00:10:26,620 --> 00:10:28,220 it never does. 211 00:10:28,220 --> 00:10:30,760 So the situation is called a deadlock. 212 00:10:30,760 --> 00:10:33,970 And it's obvious to spot, because all of your threads 213 00:10:33,970 --> 00:10:36,250 are going to be stuck doing absolutely nothing. 214 00:10:36,250 --> 00:10:37,920 Your CPU is not doing anything. 215 00:10:37,920 --> 00:10:41,020 And you're just sitting there. 216 00:10:41,020 --> 00:10:45,770 So a very common work-around that people like for this is 217 00:10:45,770 --> 00:10:48,360 to use what's called a try lock pattern. 218 00:10:48,360 --> 00:10:53,570 So what you do is you grab a lock on one of them, like, 219 00:10:53,570 --> 00:10:54,840 say, your left one. 220 00:10:54,840 --> 00:10:57,490 And then for the right one, instead of directly going and 221 00:10:57,490 --> 00:10:59,590 trying to grab the lock, you ask-- 222 00:10:59,590 --> 00:11:01,010 you basically do-- 223 00:11:01,010 --> 00:11:03,520 if the thing is unlocked, grab it. 224 00:11:03,520 --> 00:11:04,500 Otherwise, don't grab it. 225 00:11:04,500 --> 00:11:06,780 So it's a non-blocking approach to 226 00:11:06,780 --> 00:11:07,870 trying to get a lock. 227 00:11:07,870 --> 00:11:09,815 So it either succeeds and you have the lock, or 228 00:11:09,815 --> 00:11:11,480 it instantly fails. 229 00:11:11,480 --> 00:11:14,460 And if it fails, then you switch the order of which-- 230 00:11:14,460 --> 00:11:17,340 you put down the chopstick that you grabbed, and then you 231 00:11:17,340 --> 00:11:18,280 try the next one. 232 00:11:18,280 --> 00:11:21,410 Maybe you wait a little bit before then. 233 00:11:21,410 --> 00:11:26,510 This is more or less than what I did for your beta test, for 234 00:11:26,510 --> 00:11:28,520 your unit test tester. 235 00:11:28,520 --> 00:11:30,020 When it fails to-- 236 00:11:30,020 --> 00:11:32,790 if first grabs one student's directory's locks. 237 00:11:32,790 --> 00:11:34,850 And then it tries to grab the second one. 238 00:11:34,850 --> 00:11:37,970 If that fails, then it puts down both locks, and then it 239 00:11:37,970 --> 00:11:40,420 waits a little bit, and then it tries again. 240 00:11:40,420 --> 00:11:42,955 So what's the problem with this approach? 241 00:11:50,290 --> 00:11:50,605 Yes? 242 00:11:50,605 --> 00:11:51,855 AUDIENCE: It can still hold up. 243 00:11:54,380 --> 00:11:54,780 PROFESSOR: What's that? 244 00:11:54,780 --> 00:11:58,447 AUDIENCE: It can keep waiting and grabbing, and sometimes it 245 00:11:58,447 --> 00:11:59,181 will contend. 246 00:11:59,181 --> 00:12:01,790 PROFESSOR: Yeah, pretty much, the same problem happens. 247 00:12:01,790 --> 00:12:04,990 Only now you have the case where everybody grabs their 248 00:12:04,990 --> 00:12:06,900 left, and now the right one's gone. 249 00:12:06,900 --> 00:12:08,310 So they put down their left one. 250 00:12:08,310 --> 00:12:10,420 And then they all go to grab the right one. 251 00:12:10,420 --> 00:12:11,940 Now they have the right one, and now they 252 00:12:11,940 --> 00:12:12,650 want the left one. 253 00:12:12,650 --> 00:12:14,100 But the left one not there. 254 00:12:14,100 --> 00:12:16,730 So in theory, they can end up doing this for a 255 00:12:16,730 --> 00:12:17,980 very, very long time. 256 00:12:20,900 --> 00:12:23,410 But in practice what happens is because of scheduling 257 00:12:23,410 --> 00:12:26,270 overhead, and the phase of the moon and whatever else affects 258 00:12:26,270 --> 00:12:30,170 computing, you'll end up after a while, this become distinct 259 00:12:30,170 --> 00:12:32,160 from this pattern and eventually all the locks go 260 00:12:32,160 --> 00:12:33,740 through, and you're OK. 261 00:12:33,740 --> 00:12:36,940 But in the meantime, you spent a lot of time spinning, trying 262 00:12:36,940 --> 00:12:38,190 to grab locks. 263 00:12:38,190 --> 00:12:41,610 And so this situation is called a livelock. 264 00:12:41,610 --> 00:12:43,420 And it's a lot more annoying than a 265 00:12:43,420 --> 00:12:45,160 deadlock because it happens-- 266 00:12:45,160 --> 00:12:47,350 it tends to be less reproducible. 267 00:12:47,350 --> 00:12:50,170 And it's harder to diagnose, because if you're looking at 268 00:12:50,170 --> 00:12:52,480 top or your favorite CPU monitor, you see that the 269 00:12:52,480 --> 00:12:54,400 program seems to be making progress. 270 00:12:54,400 --> 00:12:57,200 Maybe some of them actually get the lock and go through. 271 00:12:57,200 --> 00:12:58,480 But the rest of them don't. 272 00:12:58,480 --> 00:13:00,790 So it's hard to argue whether or not 273 00:13:00,790 --> 00:13:02,830 there's correctness issue. 274 00:13:02,830 --> 00:13:07,030 Now there's various classes of solutions to the dining 275 00:13:07,030 --> 00:13:09,700 philosophers problem, but you guys can go look that up. 276 00:13:09,700 --> 00:13:13,430 I'm not going to go over them. 277 00:13:13,430 --> 00:13:19,770 So another issue with synchronization is suppose you 278 00:13:19,770 --> 00:13:21,390 have two threads. 279 00:13:21,390 --> 00:13:25,110 Let's say this is a Mars Rover, and it's on Mars. 280 00:13:25,110 --> 00:13:28,670 And the two things that the programmer wanted to do are 281 00:13:28,670 --> 00:13:32,980 send back its debugging log, so that the nerdier people at 282 00:13:32,980 --> 00:13:35,560 NASA, I suppose, can read them over, or whatever 283 00:13:35,560 --> 00:13:37,040 they do with logs. 284 00:13:37,040 --> 00:13:40,060 And the high priority, what everybody actually wants, is 285 00:13:40,060 --> 00:13:43,090 for the Rover to send back pictures. 286 00:13:43,090 --> 00:13:45,420 Now both of these things require access to the radio 287 00:13:45,420 --> 00:13:48,850 that's supposed to transfer something. 288 00:13:48,850 --> 00:13:50,580 And only one thing can transmit at time. 289 00:13:50,580 --> 00:13:52,000 Otherwise, the transmission is garbled. 290 00:13:52,000 --> 00:13:55,870 So a reasonable approach might be to just lock the radio in 291 00:13:55,870 --> 00:13:59,240 each thread before you transmit, and then unlock 292 00:13:59,240 --> 00:14:01,330 after you transmit. 293 00:14:01,330 --> 00:14:04,100 So what could be a potential issue with this? 294 00:14:10,004 --> 00:14:11,254 AUDIENCE: One might get all the time. 295 00:14:13,460 --> 00:14:19,070 PROFESSOR: Let's say, the scheduler interrupts every 10 296 00:14:19,070 --> 00:14:23,450 milliseconds, and then 1 out of the 10 times, it allows 10 297 00:14:23,450 --> 00:14:24,420 logs to run. 298 00:14:24,420 --> 00:14:26,520 And then 9 out of the 10 times, it will allow some 299 00:14:26,520 --> 00:14:27,290 pictures to run. 300 00:14:27,290 --> 00:14:32,280 So everybody gets time scheduled. 301 00:14:32,280 --> 00:14:36,180 So I guess the easiest way to illustrate this is what 302 00:14:36,180 --> 00:14:42,260 happens if it's currently running said logs, and it 303 00:14:42,260 --> 00:14:43,580 grabs this lock. 304 00:14:43,580 --> 00:14:45,670 And then while it's transmitting, let's say on the 305 00:14:45,670 --> 00:14:48,360 second megabyte, the scheduler says your time is up. 306 00:14:48,360 --> 00:14:52,480 And then it swaps in this program, and it tries to run. 307 00:14:52,480 --> 00:14:55,970 So now when this program runs, it tries to lock the radio, 308 00:14:55,970 --> 00:14:57,770 but the radio's already locked. 309 00:14:57,770 --> 00:14:59,610 And the one that locked the radio is 310 00:14:59,610 --> 00:15:01,140 the send locks thread. 311 00:15:01,140 --> 00:15:04,100 And so it could sit there and spin for a while waiting for 312 00:15:04,100 --> 00:15:06,810 the lock to be available. 313 00:15:06,810 --> 00:15:08,460 But that's not going to happen. 314 00:15:08,460 --> 00:15:11,400 Because the guy that's holding the lock is a bug. 315 00:15:11,400 --> 00:15:17,160 So in general, this is called starvation, where in the 316 00:15:17,160 --> 00:15:21,050 process of having a shared resource, you end up unfairly 317 00:15:21,050 --> 00:15:23,690 depriving someone else of a resource when you're 318 00:15:23,690 --> 00:15:27,010 not truly using it. 319 00:15:27,010 --> 00:15:28,860 Well, I guess that's not the-- 320 00:15:28,860 --> 00:15:32,030 I guess you are using it, but you're using it for longer 321 00:15:32,030 --> 00:15:33,390 than is fair for you. 322 00:15:33,390 --> 00:15:36,380 Like in the scheduler you wanted 90% to one process and 323 00:15:36,380 --> 00:15:39,360 10% to the other, but in reality you end up with a 324 00:15:39,360 --> 00:15:41,100 completely different set of priorities. 325 00:15:41,100 --> 00:15:44,980 And this inversion of priorities is commonly called 326 00:15:44,980 --> 00:15:48,200 priority inversion. 327 00:15:48,200 --> 00:15:49,450 Does that make sense? 328 00:15:51,510 --> 00:15:52,280 Cool. 329 00:15:52,280 --> 00:15:56,950 So on a completely different topic. 330 00:15:56,950 --> 00:15:59,660 So Cilk hyperobjects were covered 331 00:15:59,660 --> 00:16:00,860 extensively in lecture. 332 00:16:00,860 --> 00:16:03,790 You guys had a problem set on it, although it was not 333 00:16:03,790 --> 00:16:07,100 received very warmly from what I see in the 334 00:16:07,100 --> 00:16:08,970 problems sets write ups. 335 00:16:08,970 --> 00:16:14,020 But I think all of the basic material for what a Cilk 336 00:16:14,020 --> 00:16:17,740 hyperobjects is and what it does can be found in the 337 00:16:17,740 --> 00:16:19,970 lecture material. 338 00:16:19,970 --> 00:16:23,630 But more interesting, let's explore what you can do with 339 00:16:23,630 --> 00:16:28,440 hyperobjects that aren't in the documentation. 340 00:16:28,440 --> 00:16:32,540 So I'm going to define a piece of code here. 341 00:16:32,540 --> 00:16:37,840 And it's C++ or Cilk++ code. 342 00:16:37,840 --> 00:16:40,320 And the first part of it defines a very simple 343 00:16:40,320 --> 00:16:42,560 structure called a point. 344 00:16:42,560 --> 00:16:44,960 And it has three members. 345 00:16:44,960 --> 00:16:47,930 Or actually it has two members, x and y, and it has 346 00:16:47,930 --> 00:16:51,660 three methods for setting the values of x and y and also 347 00:16:51,660 --> 00:16:54,610 getting the values of x and y. 348 00:16:54,610 --> 00:16:55,910 Question? 349 00:16:55,910 --> 00:16:56,330 No? 350 00:16:56,330 --> 00:16:57,680 OK. 351 00:16:57,680 --> 00:17:02,370 And then there's also a hyperpoint class which 352 00:17:02,370 --> 00:17:04,650 contains some extra Cilk junk. 353 00:17:04,650 --> 00:17:07,750 And it also implements the same three methods. 354 00:17:07,750 --> 00:17:11,020 Set, get x, and get y. 355 00:17:11,020 --> 00:17:17,589 And if you look at the monoid that it contains the point 356 00:17:17,589 --> 00:17:22,930 monoid it implements a reduce function that 357 00:17:22,930 --> 00:17:26,530 just doesn't do anything. 358 00:17:26,530 --> 00:17:33,080 And for the public methods, the setters and getters, they 359 00:17:33,080 --> 00:17:37,150 grab the point represented by the local view to the reducer 360 00:17:37,150 --> 00:17:38,460 that it contains. 361 00:17:38,460 --> 00:17:44,730 And it calls the method that you called on that point. 362 00:17:44,730 --> 00:17:49,310 So the question is what does this thing do, 363 00:17:49,310 --> 00:17:50,560 the hyperpoint object? 364 00:17:55,840 --> 00:17:57,730 Anybody have any wild guesses at this point? 365 00:18:01,730 --> 00:18:02,650 That's a no. 366 00:18:02,650 --> 00:18:03,990 So OK. 367 00:18:03,990 --> 00:18:06,150 Let's try using this code. 368 00:18:06,150 --> 00:18:08,370 So to put the example into perspective. 369 00:18:08,370 --> 00:18:13,710 Suppose I have this artificially contrived 370 00:18:13,710 --> 00:18:19,980 function that takes an array of 100 points, and it tries to 371 00:18:19,980 --> 00:18:24,120 do an in place reversal of its elements. 372 00:18:24,120 --> 00:18:27,900 So one way that it can do that is you have a 373 00:18:27,900 --> 00:18:30,450 global temporary point. 374 00:18:30,450 --> 00:18:35,770 And you, at every step of the iteration, first you step 375 00:18:35,770 --> 00:18:37,010 through half of the list. 376 00:18:37,010 --> 00:18:42,310 And then at every step of the iteration, you copy the ith 377 00:18:42,310 --> 00:18:45,710 element into the temporary variable. 378 00:18:45,710 --> 00:18:54,040 And then you set the ith from the other end to the-- 379 00:18:54,040 --> 00:18:55,290 you swap the two. 380 00:18:55,290 --> 00:18:58,190 And then you-- 381 00:18:58,190 --> 00:19:02,020 yeah, so if it is a three-variable swap, I guess 382 00:19:02,020 --> 00:19:03,970 is the simplest way of explaining it. 383 00:19:03,970 --> 00:19:07,790 It's a swap using a using a temporary variable. 384 00:19:07,790 --> 00:19:11,080 Anyone not get what that code does, despite my attempts to 385 00:19:11,080 --> 00:19:12,330 confuse you? 386 00:19:16,600 --> 00:19:23,520 So as far as this space complexity of this procedure, 387 00:19:23,520 --> 00:19:28,110 really what it needs at minimum is enough memory to 388 00:19:28,110 --> 00:19:32,580 store the temporary point, and then one register to use to 389 00:19:32,580 --> 00:19:33,780 put in the temporary values. 390 00:19:33,780 --> 00:19:37,900 You can think of a solution that uses only one register to 391 00:19:37,900 --> 00:19:41,800 update values within your point structure. 392 00:19:41,800 --> 00:19:48,380 And so let's suppose I want to do this in parallel. 393 00:19:48,380 --> 00:19:52,800 And so what I do is I call it parallel reverse, and I 394 00:19:52,800 --> 00:19:56,100 replace for with Cilk for. 395 00:19:56,100 --> 00:20:00,610 So am I done? 396 00:20:00,610 --> 00:20:02,246 What's wrong with my code? 397 00:20:02,246 --> 00:20:03,950 AUDIENCE: Race. 398 00:20:03,950 --> 00:20:05,850 PROFESSOR: Yes. 399 00:20:05,850 --> 00:20:08,420 Well first it takes that much-- it takes the same 400 00:20:08,420 --> 00:20:09,550 amount of space. 401 00:20:09,550 --> 00:20:13,470 But there is a data race on temp, because multiple threads 402 00:20:13,470 --> 00:20:15,690 could be updating temp. 403 00:20:15,690 --> 00:20:22,100 So now what I do is I replace my point with a hyperpoint. 404 00:20:25,940 --> 00:20:28,720 So now what does the hyperpoint do? 405 00:20:28,720 --> 00:20:38,020 So within each iteration of the Cilk for loop, so if that 406 00:20:38,020 --> 00:20:40,840 iteration has been-- if the work of that iteration has 407 00:20:40,840 --> 00:20:43,310 been stolen or spawned off. 408 00:20:43,310 --> 00:20:48,160 Then the hyperobject, because it has a reducer within it, 409 00:20:48,160 --> 00:20:50,230 it'll get a new local view which is a new 410 00:20:50,230 --> 00:20:52,510 point object to use. 411 00:20:52,510 --> 00:20:56,010 And if it's not still in that it continues running in the 412 00:20:56,010 --> 00:20:59,120 same thread, then it actually just continues using the local 413 00:20:59,120 --> 00:21:02,370 view that was previously instantiated. 414 00:21:02,370 --> 00:21:07,050 So no matter what Cilk does in the background, you're 415 00:21:07,050 --> 00:21:11,160 guaranteed to not have any data races on temp, because 416 00:21:11,160 --> 00:21:14,430 whenever you spawn off a new thread, the hyperobject will 417 00:21:14,430 --> 00:21:19,140 instantiate a new temp object for you to use. 418 00:21:19,140 --> 00:21:22,140 And this is an example of what's called thread local 419 00:21:22,140 --> 00:21:25,700 storage, so like a temporary storage space for each thread. 420 00:21:28,450 --> 00:21:29,700 Any questions? 421 00:21:32,900 --> 00:21:34,150 Cool. 422 00:21:38,040 --> 00:21:44,020 So on the quiz, you might be asked about various abusing of 423 00:21:44,020 --> 00:21:47,040 various other novel hyperobjects that don't do the 424 00:21:47,040 --> 00:21:49,310 typical thing, which is take a left and 425 00:21:49,310 --> 00:21:50,740 right and reduce them. 426 00:21:50,740 --> 00:21:52,900 They might do something a little bit quirky. 427 00:21:52,900 --> 00:21:57,600 And you might be asked to explain what they do. 428 00:21:57,600 --> 00:21:57,870 AUDIENCE: Maybe? 429 00:21:57,870 --> 00:21:58,842 PROFESSOR: Yes? 430 00:21:58,842 --> 00:21:59,786 Maybe. 431 00:21:59,786 --> 00:22:00,980 Maybe. 432 00:22:00,980 --> 00:22:04,924 AUDIENCE: But this is purely for illustrating that you can 433 00:22:04,924 --> 00:22:07,882 do such a thing with hyperobjects. 434 00:22:07,882 --> 00:22:12,320 Because you can always create a temporary variable there. 435 00:22:12,320 --> 00:22:16,070 PROFESSOR: But suppose point was a much larger object. 436 00:22:16,070 --> 00:22:19,750 Sure, this is a contrived example. 437 00:22:19,750 --> 00:22:21,000 But yes. 438 00:22:24,630 --> 00:22:26,740 Anyone? 439 00:22:26,740 --> 00:22:28,838 Everyone gets this? 440 00:22:28,838 --> 00:22:33,329 So, in that case, why would that problem be more efficient 441 00:22:33,329 --> 00:22:35,824 than creating a new copy of it, say another point? 442 00:22:38,330 --> 00:22:40,630 PROFESSOR: Because if you think about the case where 443 00:22:40,630 --> 00:22:44,430 this code runs on a single processor with no work 444 00:22:44,430 --> 00:22:48,780 stealing, this version does the exact same thing as the 445 00:22:48,780 --> 00:22:50,940 single threaded version. 446 00:22:50,940 --> 00:22:53,180 No extra objects are being created. 447 00:22:53,180 --> 00:22:57,070 And if you're running on however many processors and 448 00:22:57,070 --> 00:23:00,060 Cilk decides what to do in the background as far as how many 449 00:23:00,060 --> 00:23:03,600 threads to allocate for you, and your code doesn't have to 450 00:23:03,600 --> 00:23:06,568 know anything about that. 451 00:23:06,568 --> 00:23:09,907 AUDIENCE: What's the monoid again? 452 00:23:09,907 --> 00:23:15,850 PROFESSOR: The monoid is the associative operator that has 453 00:23:15,850 --> 00:23:20,570 an identity and a reduce operation and some other 454 00:23:20,570 --> 00:23:21,820 things that I forgot. 455 00:23:33,310 --> 00:23:35,840 Any more questions? 456 00:23:35,840 --> 00:23:37,300 Cool. 457 00:23:37,300 --> 00:23:40,590 So switching gears, and this time I actually have a 458 00:23:40,590 --> 00:23:48,150 placeholder slide for it, next part is more about like the 459 00:23:48,150 --> 00:23:50,750 types of things that you might have learned from doing or 460 00:23:50,750 --> 00:23:51,810 experience you might have gained 461 00:23:51,810 --> 00:23:53,910 from doing your projects. 462 00:23:53,910 --> 00:23:58,790 And it primarily pertains to lab oriented, like in practice 463 00:23:58,790 --> 00:24:02,460 hands on things, as opposed to theoretical concepts. 464 00:24:02,460 --> 00:24:08,590 So just as a fun warm up, everybody has hopefully at 465 00:24:08,590 --> 00:24:12,130 this point used some STL data structure. 466 00:24:12,130 --> 00:24:14,650 Vectors should definitely look familiar. 467 00:24:14,650 --> 00:24:18,720 So let's compare some operations on these three. 468 00:24:18,720 --> 00:24:23,700 Because, as far as the API is concerned, both list-- 469 00:24:23,700 --> 00:24:26,900 all three of them support almost the same set of 470 00:24:26,900 --> 00:24:32,780 functions, as far as Insert, at pushback, pop front. 471 00:24:32,780 --> 00:24:35,890 All those operations are supported by these things. 472 00:24:35,890 --> 00:24:36,980 So it's kind of-- 473 00:24:36,980 --> 00:24:40,100 You might ask why would you use one over the other? 474 00:24:40,100 --> 00:24:42,340 Well, it turns out that they have slightly different 475 00:24:42,340 --> 00:24:45,510 performance characteristics that are useful in noting. 476 00:24:45,510 --> 00:24:50,130 So anyone want to compare and contrast like what data 477 00:24:50,130 --> 00:24:52,575 structure a list corresponds to compared to a vector? 478 00:24:58,540 --> 00:25:02,760 So which one would be like a linked list? 479 00:25:02,760 --> 00:25:04,640 List, yep. 480 00:25:04,640 --> 00:25:11,270 And then vector obviously is a dynamically growing array. 481 00:25:11,270 --> 00:25:12,640 And a deque-- 482 00:25:12,640 --> 00:25:15,540 how many people have used the deque? 483 00:25:15,540 --> 00:25:15,860 Cool. 484 00:25:15,860 --> 00:25:16,130 One. 485 00:25:16,130 --> 00:25:18,290 How many people know what deque does even if they 486 00:25:18,290 --> 00:25:21,090 haven't used it? 487 00:25:21,090 --> 00:25:21,740 Three? 488 00:25:21,740 --> 00:25:22,610 Four? 489 00:25:22,610 --> 00:25:23,240 OK. 490 00:25:23,240 --> 00:25:26,980 So a deque is actually implemented similar to a 491 00:25:26,980 --> 00:25:30,760 vector, but it's dynamically growing on both ends. 492 00:25:39,170 --> 00:25:41,710 OK, so let's start with filling in the 493 00:25:41,710 --> 00:25:43,310 table for the list. 494 00:25:43,310 --> 00:25:47,650 So inserting and removing at the end of a list. 495 00:25:47,650 --> 00:25:48,330 Constant time? 496 00:25:48,330 --> 00:25:50,930 Linear time? 497 00:25:50,930 --> 00:25:54,160 How many people say constant time? 498 00:25:54,160 --> 00:25:56,360 Linear? 499 00:25:56,360 --> 00:25:57,930 Half and half, wow. 500 00:25:57,930 --> 00:26:00,120 Don't rely on your neighbor during the test. 501 00:26:03,480 --> 00:26:05,180 So it's actually constant time. 502 00:26:05,180 --> 00:26:09,460 If you think about appending to the end of a linked list, 503 00:26:09,460 --> 00:26:14,070 it's just a matter of couple pointer operations. 504 00:26:14,070 --> 00:26:17,280 How about inserting and removing at the front? 505 00:26:17,280 --> 00:26:19,450 Constant? 506 00:26:19,450 --> 00:26:19,980 Cool. 507 00:26:19,980 --> 00:26:21,590 Linear? 508 00:26:21,590 --> 00:26:21,860 OK. 509 00:26:21,860 --> 00:26:23,340 I'll stop picking on people now. 510 00:26:26,760 --> 00:26:30,930 So next is inserting and removing an arbitrary offset. 511 00:26:30,930 --> 00:26:34,810 So what I mean by that is you have an iterator to a 512 00:26:34,810 --> 00:26:37,520 particular point inside the list. 513 00:26:37,520 --> 00:26:44,010 Now I say insert this element five or n elements away from 514 00:26:44,010 --> 00:26:45,480 that iterator. 515 00:26:45,480 --> 00:26:47,070 How long does that operation take? 516 00:26:50,660 --> 00:26:53,320 How many people say constant time? 517 00:26:53,320 --> 00:26:53,980 Three people. 518 00:26:53,980 --> 00:26:57,220 How many people say some sort of linear time? 519 00:26:57,220 --> 00:26:58,760 I agree with you guys. 520 00:26:58,760 --> 00:27:00,650 It is indeed a linear time thing, 521 00:27:00,650 --> 00:27:01,990 because you have to traverse-- 522 00:27:01,990 --> 00:27:04,640 you have to actually fall the next pointers to the location 523 00:27:04,640 --> 00:27:06,410 or the previous pointers to the location 524 00:27:06,410 --> 00:27:08,210 that you want to insert. 525 00:27:08,210 --> 00:27:13,630 So although list might appear to support randomish axis, 526 00:27:13,630 --> 00:27:17,610 like you can add numbers to the iterator, it doesn't 527 00:27:17,610 --> 00:27:20,490 actually support that operation efficiently in the 528 00:27:20,490 --> 00:27:21,730 background. 529 00:27:21,730 --> 00:27:24,720 Now the next one is also kind of tricky. 530 00:27:24,720 --> 00:27:25,620 Checking the size. 531 00:27:25,620 --> 00:27:28,690 Like checking how many elements are calling the dot 532 00:27:28,690 --> 00:27:33,010 size method of a standard list. 533 00:27:33,010 --> 00:27:36,224 How many people think that's constant? 534 00:27:36,224 --> 00:27:36,670 Cool. 535 00:27:36,670 --> 00:27:38,110 About four or five. 536 00:27:38,110 --> 00:27:40,840 How many people think that's linear? 537 00:27:40,840 --> 00:27:42,670 One. 538 00:27:42,670 --> 00:27:45,710 How many people think it's possible to have a linked list 539 00:27:45,710 --> 00:27:49,200 data structure that's forced constant time? 540 00:27:49,200 --> 00:27:50,180 There we go. 541 00:27:50,180 --> 00:27:55,506 Well, unfortunately, the STL only requires you to have a 542 00:27:55,506 --> 00:27:59,730 big O of n time for this. 543 00:27:59,730 --> 00:28:04,440 In fact, I peeked inside the code for glibc the lib 544 00:28:04,440 --> 00:28:07,300 standard C++ that is used on the cloud machines. 545 00:28:07,300 --> 00:28:09,430 And in fact, what they do is they actually walk through 546 00:28:09,430 --> 00:28:11,250 everything from start to end, and they count up 547 00:28:11,250 --> 00:28:12,490 the number of times. 548 00:28:12,490 --> 00:28:15,270 So in fact, it is a linear time operation, although I'm 549 00:28:15,270 --> 00:28:17,760 sure somewhere out in the world, there exists a C 550 00:28:17,760 --> 00:28:22,030 library, C++ library that does linear time, or constant time, 551 00:28:22,030 --> 00:28:23,130 size look ups. 552 00:28:23,130 --> 00:28:26,420 So you might want to be careful about that one. 553 00:28:26,420 --> 00:28:29,380 On a different note, there's actually a dot empty method 554 00:28:29,380 --> 00:28:32,680 for checking whether or not a list is empty, and for any 555 00:28:32,680 --> 00:28:35,510 type of STL collection that is guaranteed 556 00:28:35,510 --> 00:28:36,620 to be constant time. 557 00:28:36,620 --> 00:28:38,820 So if you just want to know whether something's empty, 558 00:28:38,820 --> 00:28:42,700 don't use dot size equals 0. 559 00:28:42,700 --> 00:28:46,120 What about reversing a linked list in place? 560 00:28:46,120 --> 00:28:48,460 Linear? 561 00:28:48,460 --> 00:28:50,210 More than linear? 562 00:28:50,210 --> 00:28:52,760 It's not a technical term, and Charles is probably going to 563 00:28:52,760 --> 00:28:55,660 hurt me now. 564 00:28:55,660 --> 00:28:58,110 Linear? 565 00:28:58,110 --> 00:28:58,640 Yes. 566 00:28:58,640 --> 00:29:00,990 Linear. 567 00:29:00,990 --> 00:29:05,120 What about in place sorting of a linked list? 568 00:29:05,120 --> 00:29:06,370 How many people think it's N log(N)? 569 00:29:10,140 --> 00:29:12,900 One or two daring souls. 570 00:29:12,900 --> 00:29:13,940 Three daring souls. 571 00:29:13,940 --> 00:29:15,630 A well informed daring soul. 572 00:29:15,630 --> 00:29:17,470 How many people think it's more than N log(N)? 573 00:29:22,030 --> 00:29:22,800 One. 574 00:29:22,800 --> 00:29:23,370 OK. 575 00:29:23,370 --> 00:29:25,780 So actually it is N log(N). 576 00:29:25,780 --> 00:29:28,980 And that's actually not specified by the specs. 577 00:29:28,980 --> 00:29:30,680 But it happens to be. 578 00:29:30,680 --> 00:29:33,060 And it turns out that there is a variant merge sort that 579 00:29:33,060 --> 00:29:36,220 works on link list that is N log(N). 580 00:29:36,220 --> 00:29:38,950 I didn't know that, but anyway. 581 00:29:38,950 --> 00:29:42,850 So how about let's fill this in for the vector. 582 00:29:42,850 --> 00:29:45,560 Inserting and removing an element at the end-- 583 00:29:45,560 --> 00:29:47,660 constant time? 584 00:29:47,660 --> 00:29:50,250 Linear time? 585 00:29:50,250 --> 00:29:52,840 Nobody says linear time. 586 00:29:52,840 --> 00:29:55,950 So it's amortized constant time, I guess. 587 00:29:55,950 --> 00:29:59,380 I'll just call it constant time. 588 00:29:59,380 --> 00:30:00,990 What about inserting or removing at 589 00:30:00,990 --> 00:30:03,500 the front of a vector-- 590 00:30:03,500 --> 00:30:05,590 constant time? 591 00:30:05,590 --> 00:30:08,500 Linear time? 592 00:30:08,500 --> 00:30:09,130 Come on, guys. 593 00:30:09,130 --> 00:30:11,760 I'm getting like three hands for linear time and zero for 594 00:30:11,760 --> 00:30:12,850 constant time. 595 00:30:12,850 --> 00:30:15,780 I guess that's reasonable. 596 00:30:15,780 --> 00:30:20,480 So it does, in fact, insert one element. 597 00:30:20,480 --> 00:30:22,660 It puts the element in and then it grows the vector in. 598 00:30:22,660 --> 00:30:24,540 It copies everything in. 599 00:30:24,540 --> 00:30:28,590 So don't insert at the front, don't insert or remove at the 600 00:30:28,590 --> 00:30:29,540 front of a vector. 601 00:30:29,540 --> 00:30:33,160 It's a very bad idea if you do that a lot. 602 00:30:33,160 --> 00:30:35,750 What about inserting or removing at an arbitrary 603 00:30:35,750 --> 00:30:37,000 location inside a vector? 604 00:30:39,450 --> 00:30:43,790 Well, that one's fairly obvious to be some sort of 605 00:30:43,790 --> 00:30:46,110 linear time too, because it has to shift all of the 606 00:30:46,110 --> 00:30:49,020 elements after it. 607 00:30:49,020 --> 00:30:50,270 Checking the size of the vector? 608 00:30:55,720 --> 00:30:59,030 Some people are getting pessimistic about the STL. 609 00:30:59,030 --> 00:31:01,090 That's my personal opinion, but I won't 610 00:31:01,090 --> 00:31:02,830 transfer that onto you. 611 00:31:02,830 --> 00:31:05,630 So it turns out that for a vector, yes, it is constant 612 00:31:05,630 --> 00:31:07,070 time to check the size. 613 00:31:07,070 --> 00:31:09,020 So that's OK. 614 00:31:09,020 --> 00:31:11,980 In place reversal, linear time. 615 00:31:11,980 --> 00:31:15,950 And sorting is N log(N), which is not 616 00:31:15,950 --> 00:31:17,910 surprising by any means. 617 00:31:17,910 --> 00:31:19,990 So a deque? 618 00:31:19,990 --> 00:31:23,000 Inserting or removing at the end-- 619 00:31:23,000 --> 00:31:25,410 constant? 620 00:31:25,410 --> 00:31:27,060 Sure, constant. 621 00:31:27,060 --> 00:31:31,210 And inserting or removing at the front? 622 00:31:31,210 --> 00:31:31,690 Cool. 623 00:31:31,690 --> 00:31:32,440 Constant. 624 00:31:32,440 --> 00:31:34,150 So that's the primary difference between 625 00:31:34,150 --> 00:31:35,480 a deque and a vector. 626 00:31:35,480 --> 00:31:40,100 And for everything else, it behaves exactly like a vector. 627 00:31:40,100 --> 00:31:42,880 Does that makes sense? 628 00:31:42,880 --> 00:31:43,380 Yes. 629 00:31:43,380 --> 00:31:46,990 AUDIENCE: So is list like a doubly linked list? 630 00:31:46,990 --> 00:31:49,840 PROFESSOR: A standard list is in fact a doubly linked list. 631 00:31:49,840 --> 00:31:52,520 So it supports both forward and reverse traversal. 632 00:31:52,520 --> 00:31:56,590 There's a standard S list, which is a singly linked list, 633 00:31:56,590 --> 00:31:58,240 and it only supports forward traversal. 634 00:32:02,300 --> 00:32:03,550 Any other questions? 635 00:32:07,740 --> 00:32:11,730 Moving on to a slightly different topic, can anyone 636 00:32:11,730 --> 00:32:14,580 point out what is bad about this code? 637 00:32:14,580 --> 00:32:16,695 And I mean from a performance standpoint. 638 00:32:20,980 --> 00:32:22,230 AUDIENCE: It's O of n. 639 00:32:32,870 --> 00:32:33,230 PROFESSOR: All right. 640 00:32:33,230 --> 00:32:35,800 Someone said it, so it's O of n. 641 00:32:35,800 --> 00:32:41,900 So the vector that's passed in here is passed in by value, 642 00:32:41,900 --> 00:32:45,490 which means whenever you call this function, it'll actually 643 00:32:45,490 --> 00:32:47,780 make a brand new copy of the vector and 644 00:32:47,780 --> 00:32:48,850 copy all of the elements. 645 00:32:48,850 --> 00:32:51,060 So it's linear time with respect to the number of 646 00:32:51,060 --> 00:32:52,310 elements in the vector. 647 00:32:55,020 --> 00:32:57,660 PROFESSOR: So how do you fix that? 648 00:32:57,660 --> 00:32:58,910 AUDIENCE: You can pass in a pointer. 649 00:33:05,200 --> 00:33:08,220 PROFESSOR: So there's two ways. 650 00:33:08,220 --> 00:33:11,160 So on the left is the original code, and on the right are two 651 00:33:11,160 --> 00:33:15,540 different ways to pass in just a pointer to the same thing. 652 00:33:15,540 --> 00:33:19,020 So you can do a reference pass, which is the first 653 00:33:19,020 --> 00:33:20,470 version above. 654 00:33:20,470 --> 00:33:23,870 And then you can use a dot to access the methods. 655 00:33:23,870 --> 00:33:26,500 Or you can pass in by pointer which everyone is already 656 00:33:26,500 --> 00:33:27,580 familiar with. 657 00:33:27,580 --> 00:33:30,740 And that's where you have to use arrows 658 00:33:30,740 --> 00:33:32,440 to access the elements. 659 00:33:32,440 --> 00:33:35,730 And then you also have to change the way that you call 660 00:33:35,730 --> 00:33:36,580 the function. 661 00:33:36,580 --> 00:33:41,060 So oftentimes if you just catch something in code, like 662 00:33:41,060 --> 00:33:44,520 say the final project where something is passed by value, 663 00:33:44,520 --> 00:33:47,790 where it should be passed by reference, oftentimes the 664 00:33:47,790 --> 00:33:50,970 easiest way to modify the code is to just change it to use a 665 00:33:50,970 --> 00:33:52,220 reference rather than a pointer. 666 00:33:54,890 --> 00:34:03,270 So the next thing that I want to cover is a question type 667 00:34:03,270 --> 00:34:07,970 that will be on the final, will be on the quiz. 668 00:34:07,970 --> 00:34:11,780 And I'll give some examples of problems of this form. 669 00:34:11,780 --> 00:34:15,070 But most importantly, I want everybody to be familiar with 670 00:34:15,070 --> 00:34:17,659 the form of the question, the rules involving the question, 671 00:34:17,659 --> 00:34:21,010 so nobody accidentally loses points for not reading the 672 00:34:21,010 --> 00:34:25,270 instructions, which nobody seems to do on quizzes. 673 00:34:25,270 --> 00:34:30,070 So you are given two versions of the same function written 674 00:34:30,070 --> 00:34:32,920 in C or C++. 675 00:34:32,920 --> 00:34:38,630 And you are to assume that your compiler-- 676 00:34:38,630 --> 00:34:42,159 well, the compiler, as far as like what the CPU is executing 677 00:34:42,159 --> 00:34:44,409 is a literal interpretation of the code you 678 00:34:44,409 --> 00:34:46,880 see before and after. 679 00:34:46,880 --> 00:34:49,790 By this point, everybody is probably familiar with some of 680 00:34:49,790 --> 00:34:53,880 the simple tricks a compiler does, like if you say int x 681 00:34:53,880 --> 00:34:57,280 equals 1 plus 1 there is no circumstance in which the 682 00:34:57,280 --> 00:34:59,990 compiler actually puts two 1s in two different registers and 683 00:34:59,990 --> 00:35:03,600 tells it to add it and then put it in x. 684 00:35:03,600 --> 00:35:07,480 So you are assuming that your compiler is doing a literal 685 00:35:07,480 --> 00:35:08,750 translation. 686 00:35:08,750 --> 00:35:11,760 And then you are asked to determine three properties 687 00:35:11,760 --> 00:35:14,680 about the optimization, so going from the 688 00:35:14,680 --> 00:35:17,090 before to the after. 689 00:35:17,090 --> 00:35:19,770 So the first thing is whether or not the 690 00:35:19,770 --> 00:35:21,900 optimization is legal. 691 00:35:21,900 --> 00:35:25,760 And when we define legal, we mean that the optimized 692 00:35:25,760 --> 00:35:27,930 version always has the same-- 693 00:35:27,930 --> 00:35:31,010 preserves the same behavior as the other version. 694 00:35:31,010 --> 00:35:34,470 It should be relatively simple to infer from the code 695 00:35:34,470 --> 00:35:37,520 snippets that we give you, what the intended purpose of a 696 00:35:37,520 --> 00:35:38,340 function is. 697 00:35:38,340 --> 00:35:41,330 And you are to determine whether or not the optimized 698 00:35:41,330 --> 00:35:44,520 version acts like the unoptimized version, as far as 699 00:35:44,520 --> 00:35:47,670 the correctness of the result. 700 00:35:47,670 --> 00:35:51,060 Second, you are asked to determine whether or not this 701 00:35:51,060 --> 00:35:56,350 optimized version is faster than the previous version. 702 00:35:56,350 --> 00:35:59,595 And by faster, we mean faster in most conceivable cases. 703 00:36:04,960 --> 00:36:07,240 It's a short answer question so you might want to explain 704 00:36:07,240 --> 00:36:07,750 what you mean. 705 00:36:07,750 --> 00:36:11,500 But we do expect a yes or no answer to 706 00:36:11,500 --> 00:36:12,950 start off the question. 707 00:36:12,950 --> 00:36:15,470 And it should be pretty clear whether the 708 00:36:15,470 --> 00:36:17,890 answer is yes or no. 709 00:36:17,890 --> 00:36:22,020 And then finally, I'm sure by this point everybody knows 710 00:36:22,020 --> 00:36:26,430 that when you compile with gcc -02 or -03, the compiler does 711 00:36:26,430 --> 00:36:27,900 a lot of things for you. 712 00:36:27,900 --> 00:36:30,860 So there's oftentimes no point in writing certain 713 00:36:30,860 --> 00:36:32,960 optimizations by hand, when you know when you hit the 714 00:36:32,960 --> 00:36:34,720 compile button, the compiler's going to do it in the 715 00:36:34,720 --> 00:36:36,570 background anyway. 716 00:36:36,570 --> 00:36:40,830 So this question asks whether or not you can reasonably 717 00:36:40,830 --> 00:36:43,730 assume that the optimizing compilers, like the ones that 718 00:36:43,730 --> 00:36:45,850 you're using for your projects, would do this 719 00:36:45,850 --> 00:36:48,510 optimization for you or should you take the effort to 720 00:36:48,510 --> 00:36:51,800 actually do this optimization by hand. 721 00:36:51,800 --> 00:36:57,770 And then, legalese, if the optimization is illegal, let's 722 00:36:57,770 --> 00:37:00,860 not answer whether or not it's faster or automatic. 723 00:37:00,860 --> 00:37:05,670 And if the optimization actually makes things slower, 724 00:37:05,670 --> 00:37:09,230 then let's not answer whether the compiler does it for you. 725 00:37:09,230 --> 00:37:10,850 Some of us have more cynical views of the 726 00:37:10,850 --> 00:37:12,240 compiler than others. 727 00:37:12,240 --> 00:37:16,310 So we'll just disregard that. 728 00:37:16,310 --> 00:37:17,560 Any question on the rules? 729 00:37:20,532 --> 00:37:23,906 AUDIENCE: How are we supposed to know what types of things 730 00:37:23,906 --> 00:37:25,752 the compiler's going to do, can we just read the 731 00:37:25,752 --> 00:37:27,770 documentation? 732 00:37:27,770 --> 00:37:30,840 PROFESSOR: So there was a lecture that Samaan gave 733 00:37:30,840 --> 00:37:34,340 called What Compilers Can and Cannot Do. 734 00:37:34,340 --> 00:37:37,360 AUDIENCE: So it's just stuff from that lecture? 735 00:37:37,360 --> 00:37:39,630 PROFESSOR: I would say most of it is that lecture. 736 00:37:39,630 --> 00:37:42,830 And then other things-- we might throw in a thing or two 737 00:37:42,830 --> 00:37:46,080 that you guys hopefully learn from. 738 00:37:46,080 --> 00:37:49,760 So throughout the term, we've been misguiding you on those 739 00:37:49,760 --> 00:37:52,460 walk through P-sets, suggesting you to do things 740 00:37:52,460 --> 00:37:55,620 that actually don't help. 741 00:37:55,620 --> 00:37:57,220 And you guys have gotten pretty pissed at 742 00:37:57,220 --> 00:37:58,185 us about that probably. 743 00:37:58,185 --> 00:38:01,420 But there was a method to the madness. 744 00:38:01,420 --> 00:38:05,840 I mean, there was something to be learned from that, whether 745 00:38:05,840 --> 00:38:08,830 or not we actually meant to do it. 746 00:38:08,830 --> 00:38:13,680 So hopefully some level of intuition would answer it, and 747 00:38:13,680 --> 00:38:15,980 you would get the bulk of the points for just understanding 748 00:38:15,980 --> 00:38:20,310 the points raised in the lecture. 749 00:38:20,310 --> 00:38:22,850 Any other questions about the rules? 750 00:38:22,850 --> 00:38:23,170 All right. 751 00:38:23,170 --> 00:38:26,630 So I have a couple of examples of these types of questions. 752 00:38:26,630 --> 00:38:31,380 So the first one is this. 753 00:38:31,380 --> 00:38:37,450 So it should be fairly obvious what the code does. 754 00:38:37,450 --> 00:38:43,190 It takes your input, and it wants to mod it by 256. 755 00:38:43,190 --> 00:38:45,985 So first question is this a legal optimization? 756 00:38:49,640 --> 00:38:52,250 How many people say yes? 757 00:38:52,250 --> 00:38:53,230 A lot of people. 758 00:38:53,230 --> 00:38:54,480 Anybody say no? 759 00:38:57,580 --> 00:38:59,240 Reed almost scared me for a moment there. 760 00:38:59,240 --> 00:39:00,490 He had his hand up. 761 00:39:02,990 --> 00:39:06,900 So yes, it is indeed legal. 762 00:39:06,900 --> 00:39:10,800 And it's a standard bit hack for doing a modulo 763 00:39:10,800 --> 00:39:12,240 by a power of two. 764 00:39:12,240 --> 00:39:13,490 AUDIENCE: What if it's 257? 765 00:39:18,130 --> 00:39:21,110 PROFESSOR: I was fortunate enough to make it a uint64. 766 00:39:21,110 --> 00:39:28,370 So next question is given that it's legal, is it faster to do 767 00:39:28,370 --> 00:39:31,010 the and instead of the mod? 768 00:39:31,010 --> 00:39:33,850 How many people say yes? 769 00:39:33,850 --> 00:39:37,420 How many people say no? 770 00:39:37,420 --> 00:39:39,620 So a majority of the class says yes, and 771 00:39:39,620 --> 00:39:40,780 some people say no. 772 00:39:40,780 --> 00:39:43,920 So what would be a reason why you think it's not faster? 773 00:39:43,920 --> 00:39:46,156 AUDIENCE: Well, I didn't say it's not faster faster. 774 00:39:46,156 --> 00:39:49,572 It's probably the same time, because I assume the 775 00:39:49,572 --> 00:39:53,476 instruction for modding is not actually dividing by it. 776 00:39:57,880 --> 00:39:59,880 PROFESSOR: So for the other people who said no, how many 777 00:39:59,880 --> 00:40:03,100 people agree with that line of reasoning? 778 00:40:03,100 --> 00:40:03,420 All right. 779 00:40:03,420 --> 00:40:04,700 Seems like everybody. 780 00:40:04,700 --> 00:40:09,020 So unfortunately, it is faster. 781 00:40:09,020 --> 00:40:12,480 And it turns out, I compiled down both of these pieces of 782 00:40:12,480 --> 00:40:15,670 code under-- well, actually, the compiler-- 783 00:40:15,670 --> 00:40:17,900 but anyway, I'll get to that next. 784 00:40:17,900 --> 00:40:19,550 Not giving away any answers. 785 00:40:19,550 --> 00:40:23,040 But so I executed the assembly instructions corresponding to 786 00:40:23,040 --> 00:40:24,830 both of these operations. 787 00:40:24,830 --> 00:40:28,400 And it does turn out that the compiler, the CPU, when you 788 00:40:28,400 --> 00:40:31,796 ask it to take the mod of an arbitrary number, usually it's 789 00:40:31,796 --> 00:40:33,780 an instruction called div mod. 790 00:40:33,780 --> 00:40:37,900 And what that does is that it does a divided by b, and it 791 00:40:37,900 --> 00:40:40,310 puts the dividend in one register and it puts the 792 00:40:40,310 --> 00:40:42,580 modulo in another register. 793 00:40:42,580 --> 00:40:47,480 And we do that for, let's say, 2 to the 63rd modulo 256, 794 00:40:47,480 --> 00:40:49,480 because it actually goes through all the clock cycles 795 00:40:49,480 --> 00:40:51,130 for doing that division process. 796 00:40:51,130 --> 00:40:54,660 And then it dumps out the modulo at the end. 797 00:40:54,660 --> 00:40:59,420 So yes, this actually does tend to be a lot faster. 798 00:40:59,420 --> 00:41:03,680 Now next question is will the compiler do this for you? 799 00:41:03,680 --> 00:41:05,485 How many people say yes? 800 00:41:05,485 --> 00:41:06,610 Most of the class. 801 00:41:06,610 --> 00:41:08,910 Anybody say no? 802 00:41:08,910 --> 00:41:09,430 Good. 803 00:41:09,430 --> 00:41:11,710 We all trust the compiler to some extent. 804 00:41:11,710 --> 00:41:15,280 So yeah, it turns out that gcc, starting from 01, will do 805 00:41:15,280 --> 00:41:16,530 this for you. 806 00:41:20,500 --> 00:41:23,290 Any questions? 807 00:41:23,290 --> 00:41:25,430 All right. 808 00:41:25,430 --> 00:41:28,410 Next question. 809 00:41:28,410 --> 00:41:30,310 So you have a list. 810 00:41:30,310 --> 00:41:32,920 And you pushed in. 811 00:41:32,920 --> 00:41:34,840 You pushed at the end. 812 00:41:34,840 --> 00:41:36,750 It's 42, twice. 813 00:41:36,750 --> 00:41:39,960 And then you returned the result of popping the front 814 00:41:39,960 --> 00:41:42,700 element and then popping the back element, subtracted. 815 00:41:47,290 --> 00:41:49,760 So first of all, is this a legal operation? 816 00:41:54,255 --> 00:41:57,420 Let me give everybody a chance to think. 817 00:41:57,420 --> 00:42:02,170 AUDIENCE: Legal optimization as opposed to an operation. 818 00:42:02,170 --> 00:42:03,420 PROFESSOR: Yeah. 819 00:42:05,550 --> 00:42:07,530 How many people vote yes, this is going legal? 820 00:42:10,830 --> 00:42:11,690 Roughly half the class. 821 00:42:11,690 --> 00:42:14,800 How many people say no, this is not legal? 822 00:42:14,800 --> 00:42:16,020 Two people. 823 00:42:16,020 --> 00:42:17,745 OK, so why would it not be legal? 824 00:42:22,710 --> 00:42:25,090 You can't do that. 825 00:42:25,090 --> 00:42:26,158 Yes? 826 00:42:26,158 --> 00:42:27,408 AUDIENCE: There happens to be wastefulness on some problems. 827 00:42:34,460 --> 00:42:36,090 PROFESSOR: Well, that could certainly happen. 828 00:42:36,090 --> 00:42:37,890 But for the purpose of these problems-- 829 00:42:37,890 --> 00:42:40,890 see this is why I'm bringing up these problems-- so for the 830 00:42:40,890 --> 00:42:43,270 purpose of these problems, assume there's no man behind 831 00:42:43,270 --> 00:42:44,690 the curtain doing things. 832 00:42:44,690 --> 00:42:46,980 For any given problem, you could say that's someone 833 00:42:46,980 --> 00:42:49,090 attaching a debugger to your program and changing the 834 00:42:49,090 --> 00:42:50,750 memory between instructions. 835 00:42:50,750 --> 00:42:54,764 So let's just assume that's happening. 836 00:42:54,764 --> 00:42:56,690 AUDIENCE: Also, who's local, right? 837 00:42:56,690 --> 00:42:58,090 PROFESSOR: Yeah. 838 00:42:58,090 --> 00:43:01,050 Yea, Foo is actually local, so if anybody else's doing 839 00:43:01,050 --> 00:43:04,490 anything to it, they're a very bad person. 840 00:43:04,490 --> 00:43:06,090 So fine. 841 00:43:06,090 --> 00:43:08,630 It's a legal optimization. 842 00:43:08,630 --> 00:43:10,840 Now. 843 00:43:10,840 --> 00:43:12,090 is it faster? 844 00:43:15,440 --> 00:43:18,700 How many people think that returning zero is slower than 845 00:43:18,700 --> 00:43:20,449 pushing two things up? 846 00:43:20,449 --> 00:43:22,894 AUDIENCE: [LAUGHTER] 847 00:43:22,894 --> 00:43:26,320 AUDIENCE: Depends upon how big zero is. 848 00:43:26,320 --> 00:43:27,570 PROFESSOR: That's true. 849 00:43:31,670 --> 00:43:35,280 So OK, so yes, obviously, it's faster to just 850 00:43:35,280 --> 00:43:36,910 directly return zero. 851 00:43:36,910 --> 00:43:41,250 And finally, is this an automatic optimization? 852 00:43:41,250 --> 00:43:44,340 How many people say yes? 853 00:43:44,340 --> 00:43:44,680 Cool. 854 00:43:44,680 --> 00:43:45,600 Nobody said yes. 855 00:43:45,600 --> 00:43:46,850 How many people say no? 856 00:43:51,310 --> 00:43:56,320 People who say yes, if you could work for compiler 857 00:43:56,320 --> 00:44:00,940 companies, I would appreciate that a lot. 858 00:44:00,940 --> 00:44:04,920 So unfortunately, the compiler does not make-- 859 00:44:04,920 --> 00:44:08,830 cannot reason through how an STL list works, and realize 860 00:44:08,830 --> 00:44:11,920 that what you're doing is an no op. 861 00:44:11,920 --> 00:44:15,910 It turns out that for a related set of questions, like 862 00:44:15,910 --> 00:44:18,790 have any of your mentors said anything to-- so my mentor 863 00:44:18,790 --> 00:44:19,810 said this to me last year. 864 00:44:19,810 --> 00:44:23,020 And I was pretty interested when I tried it out. 865 00:44:23,020 --> 00:44:25,795 Have you ever used a for loop to set everything in an array 866 00:44:25,795 --> 00:44:27,045 to equals 0? 867 00:44:30,130 --> 00:44:32,000 Most people seem to have done that. 868 00:44:32,000 --> 00:44:35,300 Who has used the memset or heard of the memset set API 869 00:44:35,300 --> 00:44:37,550 call before? 870 00:44:37,550 --> 00:44:39,420 A good portion of the class. 871 00:44:39,420 --> 00:44:40,290 OK, so some people. 872 00:44:40,290 --> 00:44:41,770 So a little bit of background then. 873 00:44:41,770 --> 00:44:45,700 Mem set instruction takes in an array or a pointer rather, 874 00:44:45,700 --> 00:44:48,170 and a constant, and the size of the array. 875 00:44:48,170 --> 00:44:52,050 And it sets that many elements of the array to that constant. 876 00:44:52,050 --> 00:44:56,450 So it turns out that depending on the machine that you're 877 00:44:56,450 --> 00:45:00,070 using, there is more efficient and less efficient ways of 878 00:45:00,070 --> 00:45:02,960 setting all the elements of an array to 0. 879 00:45:02,960 --> 00:45:05,760 And functions like mem set are actually are several pages 880 00:45:05,760 --> 00:45:10,160 long of hand optimized assembly to be optimal for 881 00:45:10,160 --> 00:45:12,620 your architecture. 882 00:45:12,620 --> 00:45:15,770 So it's always tempting to take a for loop that iterates 883 00:45:15,770 --> 00:45:18,060 through an array, setting everything to 0, and changing 884 00:45:18,060 --> 00:45:20,410 it to a single mem set instruction. 885 00:45:20,410 --> 00:45:27,130 And it turns out that for both gcc and icc, Intel C compiler, 886 00:45:27,130 --> 00:45:30,680 when you compile at sufficient optimization level, the 887 00:45:30,680 --> 00:45:31,940 compiler actually does this for you. 888 00:45:31,940 --> 00:45:35,000 It actually looks through the arrays. 889 00:45:35,000 --> 00:45:37,050 It actually realizes that you're setting all the members 890 00:45:37,050 --> 00:45:39,650 in the array to a constant, and it does that optimization 891 00:45:39,650 --> 00:45:43,550 for you by replacing it with a memset call. 892 00:45:43,550 --> 00:45:48,300 So just as a general question, why could it be advantageous 893 00:45:48,300 --> 00:45:52,340 for you to write the four loop as is, and have the compiler 894 00:45:52,340 --> 00:45:54,606 do the optimization for you? 895 00:45:54,606 --> 00:45:56,040 AUDIENCE: Because you later might add code in the loop. 896 00:45:58,650 --> 00:45:59,250 PROFESSOR: True. 897 00:45:59,250 --> 00:46:00,618 Any other reasons? 898 00:46:00,618 --> 00:46:02,810 PROFESSOR: I didn't hear question. 899 00:46:02,810 --> 00:46:04,510 PROFESSOR: You might want to add code that changes the 900 00:46:04,510 --> 00:46:07,350 behavior inside the loop. 901 00:46:07,350 --> 00:46:09,690 AUDIENCE: It's much more readable to have a for loop 902 00:46:09,690 --> 00:46:12,030 and you just read it, and I get that's what he's doing. 903 00:46:12,030 --> 00:46:13,600 PROFESSOR: Yes, indeed. 904 00:46:13,600 --> 00:46:16,270 Looking over some of your code submissions, it seems to be a 905 00:46:16,270 --> 00:46:19,000 non-trivial task of figuring out the size of something when 906 00:46:19,000 --> 00:46:21,980 you call malloc or memset. 907 00:46:21,980 --> 00:46:27,050 And actually, it sometimes is a non-trivial operation to 908 00:46:27,050 --> 00:46:32,540 figure out how big something is in bytes, especially for 909 00:46:32,540 --> 00:46:33,560 structs and things like that. 910 00:46:33,560 --> 00:46:37,270 So it actually is easier to let the compiler do the 911 00:46:37,270 --> 00:46:39,330 optimization for you, and you don't make any embarrassing 912 00:46:39,330 --> 00:46:40,580 mistakes in the process. 913 00:46:44,860 --> 00:46:46,110 So next question. 914 00:46:48,830 --> 00:46:51,660 So here you have a helper function. 915 00:46:51,660 --> 00:46:56,110 And in the after version, seems to do the 916 00:46:56,110 --> 00:46:57,360 same thing, does it? 917 00:47:01,310 --> 00:47:04,015 So who thinks this is a legal optimization? 918 00:47:14,350 --> 00:47:15,170 Half the class. 919 00:47:15,170 --> 00:47:16,420 Anyone think it's illegal? 920 00:47:19,220 --> 00:47:21,310 So yeah, it is legal. 921 00:47:21,310 --> 00:47:23,800 The only thing that I've done is that I've copy pasted 922 00:47:23,800 --> 00:47:27,350 basically the function body in the bottom example. 923 00:47:27,350 --> 00:47:32,790 And it's relatively easy to prove that or infer that the 924 00:47:32,790 --> 00:47:35,330 two do the same thing. 925 00:47:35,330 --> 00:47:37,385 So is it faster? 926 00:47:40,010 --> 00:47:43,290 How many people say yes? 927 00:47:43,290 --> 00:47:45,580 How many people say no? 928 00:47:45,580 --> 00:47:47,450 One person said no. 929 00:47:47,450 --> 00:47:48,410 Why is it not faster? 930 00:47:48,410 --> 00:47:52,378 AUDIENCE: I mean, I've said that it is the same speed, 931 00:47:52,378 --> 00:47:55,850 because so the only thing that would make it slower would be 932 00:47:55,850 --> 00:47:58,826 the-- you need to actually do like a compass switch. 933 00:47:58,826 --> 00:48:02,298 Because you need to call that function every time. 934 00:48:02,298 --> 00:48:05,274 But I think it could provide the concept for you-- like 935 00:48:05,274 --> 00:48:07,258 basically, it's a static function. 936 00:48:07,258 --> 00:48:08,508 It would inline it even though you don't have to declare it. 937 00:48:14,720 --> 00:48:15,030 PROFESSOR: OK. 938 00:48:15,030 --> 00:48:21,570 So if you recall the rules for the question, so basically we 939 00:48:21,570 --> 00:48:24,290 want you to interpret the code, as is, like a very 940 00:48:24,290 --> 00:48:27,100 literal interpretation as in-- 941 00:48:27,100 --> 00:48:31,930 the point was raised that for this function call, what you 942 00:48:31,930 --> 00:48:34,680 actually want to do is assume that the compiler is setting 943 00:48:34,680 --> 00:48:36,700 up a function called by putting the arguments in the 944 00:48:36,700 --> 00:48:38,990 right register and jumping to the address of 945 00:48:38,990 --> 00:48:40,440 that function above. 946 00:48:40,440 --> 00:48:44,370 So for the case of this-- for the matter-- for the purpose 947 00:48:44,370 --> 00:48:48,040 of this question, yes, it's much faster to just do a 948 00:48:48,040 --> 00:48:51,290 multiply compared to setting up a call stack and tearing it 949 00:48:51,290 --> 00:48:52,580 down after the function is done. 950 00:48:55,740 --> 00:49:00,330 Now the next question is is this automatic, which was more 951 00:49:00,330 --> 00:49:01,730 or less answered. 952 00:49:01,730 --> 00:49:04,240 And that's yes. 953 00:49:04,240 --> 00:49:08,210 So at a sufficient optimization level which is 954 00:49:08,210 --> 00:49:13,530 -03 or -02 with dash f inline functions, the compiler will 955 00:49:13,530 --> 00:49:17,760 actually use a heuristic that it has for determining whether 956 00:49:17,760 --> 00:49:20,030 or not a function is a good candidate for inlining. 957 00:49:20,030 --> 00:49:23,120 And for good candidates, it'll do the inlining for you. 958 00:49:23,120 --> 00:49:25,230 Now the specific heuristics vary 959 00:49:25,230 --> 00:49:27,040 from compiler to compiler. 960 00:49:27,040 --> 00:49:32,510 But for this specific problem that we gave you, it's a prime 961 00:49:32,510 --> 00:49:36,260 candidate for inlining, because it's declared as 962 00:49:36,260 --> 00:49:40,120 static, which means it's local to this C file. 963 00:49:40,120 --> 00:49:44,070 And it does a very simple task, a one-liner, so it 964 00:49:44,070 --> 00:49:46,020 almost certainly will be inline for you. 965 00:49:49,320 --> 00:49:50,570 Any questions? 966 00:49:52,800 --> 00:49:54,050 Cool. 967 00:49:56,470 --> 00:49:58,260 So this one. 968 00:50:03,510 --> 00:50:04,010 Question? 969 00:50:04,010 --> 00:50:05,486 AUDIENCE: I don't get it. 970 00:50:05,486 --> 00:50:06,962 Could you explain again? 971 00:50:06,962 --> 00:50:09,914 I know I've asked this before, like what's 972 00:50:09,914 --> 00:50:11,882 static, the static function? 973 00:50:11,882 --> 00:50:14,840 And it's different than in Java? 974 00:50:14,840 --> 00:50:16,590 PROFESSOR: OK. 975 00:50:16,590 --> 00:50:22,320 So the question was what's a static function in C. And so 976 00:50:22,320 --> 00:50:26,180 in C, a static function means when you declare a function as 977 00:50:26,180 --> 00:50:30,440 static, it means that the function is local to the 978 00:50:30,440 --> 00:50:32,750 current file that you're work-- the current module, the 979 00:50:32,750 --> 00:50:36,400 dot-o file, which is almost always your dot-c file. 980 00:50:36,400 --> 00:50:41,125 So like the function only exists within this dot-c file. 981 00:50:41,125 --> 00:50:43,090 A function in another dot-c file 982 00:50:43,090 --> 00:50:45,600 cannot call this function. 983 00:50:45,600 --> 00:50:47,870 So it basically allows the compiler to assume that 984 00:50:47,870 --> 00:50:50,640 there's no external effects on this function that are not 985 00:50:50,640 --> 00:50:52,010 within this file. 986 00:50:52,010 --> 00:50:54,890 Remember the compiler compiles object files one by one, and 987 00:50:54,890 --> 00:50:58,284 then the linker is the one that brings it all together. 988 00:50:58,284 --> 00:51:00,882 AUDIENCE: So the important thing is that it knows that it 989 00:51:00,882 --> 00:51:03,090 can just delete helper after it's gotten rid of it. 990 00:51:03,090 --> 00:51:03,620 PROFESSOR: Right, right. 991 00:51:03,620 --> 00:51:04,790 That's another good point. 992 00:51:04,790 --> 00:51:07,350 So in this case, after inlining, the compiler 993 00:51:07,350 --> 00:51:11,070 actually won't bother to put in the function helper inside 994 00:51:11,070 --> 00:51:13,170 the actual object file. 995 00:51:13,170 --> 00:51:15,150 So you save on my code space. 996 00:51:15,150 --> 00:51:17,140 Because the compiler knows that nowhere else this 997 00:51:17,140 --> 00:51:20,106 function can be called. 998 00:51:20,106 --> 00:51:24,100 AUDIENCE: What about static in C++? 999 00:51:24,100 --> 00:51:31,400 PROFESSOR: Static in C++ when used inside a class means that 1000 00:51:31,400 --> 00:51:35,290 the function is a static member function. 1001 00:51:35,290 --> 00:51:38,960 So it's a function that's tied to the class itself, rather 1002 00:51:38,960 --> 00:51:41,550 than an object, and instance of the class. 1003 00:51:41,550 --> 00:51:43,270 AUDIENCE: Just like Java. 1004 00:51:43,270 --> 00:51:44,520 PROFESSOR: Just like Java. 1005 00:51:47,490 --> 00:51:50,570 More questions? 1006 00:51:50,570 --> 00:51:51,450 Cool. 1007 00:51:51,450 --> 00:51:52,760 So back to this code. 1008 00:52:04,830 --> 00:52:07,900 First of all, is anyone not familiar with the syntax or 1009 00:52:07,900 --> 00:52:12,140 wants the syntax explained? 1010 00:52:12,140 --> 00:52:13,120 OK, cool. 1011 00:52:13,120 --> 00:52:17,010 So first question, is it legal? 1012 00:52:17,010 --> 00:52:18,260 How may people say yes? 1013 00:52:21,100 --> 00:52:21,790 Half the class. 1014 00:52:21,790 --> 00:52:23,040 How many people say no. 1015 00:52:25,450 --> 00:52:27,000 Roughly half the class. 1016 00:52:27,000 --> 00:52:33,020 Well, I and the people grading the quiz will side with the 1017 00:52:33,020 --> 00:52:38,410 people who say no, because down here when you're doing-- 1018 00:52:38,410 --> 00:52:40,690 this is the correct version of the XOR swap. 1019 00:52:40,690 --> 00:52:42,860 I'm not trying to trick anyone there. 1020 00:52:42,860 --> 00:52:45,460 But it turns out-- 1021 00:52:45,460 --> 00:52:50,550 well, I'd rather not assume that t, the arbitrary type 1022 00:52:50,550 --> 00:52:54,530 name, has an operator XOR defined for it that has all 1023 00:52:54,530 --> 00:52:58,110 the properties that you need in order for it to do this. 1024 00:53:00,840 --> 00:53:04,710 Like the simplest example is if I pass in a double, this 1025 00:53:04,710 --> 00:53:07,840 would not work. 1026 00:53:07,840 --> 00:53:10,280 Double does not have an operator XOR defined for it. 1027 00:53:15,060 --> 00:53:17,671 Some people look upset. 1028 00:53:17,671 --> 00:53:22,860 AUDIENCE: [LAUGHTER] 1029 00:53:22,860 --> 00:53:24,090 PROFESSOR: A list too would not have an 1030 00:53:24,090 --> 00:53:27,240 XOR defined for it. 1031 00:53:27,240 --> 00:53:29,750 Anyone disagree with me? 1032 00:53:29,750 --> 00:53:31,000 That's not a challenge. 1033 00:53:33,520 --> 00:53:35,770 So yeah, some of these questions require you to do a 1034 00:53:35,770 --> 00:53:40,090 little bit of reasoning, like reasonable reasoning, as far 1035 00:53:40,090 --> 00:53:44,290 as what to assume for the purposes of the question. 1036 00:53:44,290 --> 00:53:46,530 So watch out for that. 1037 00:53:46,530 --> 00:53:49,680 So in this case, it's not legal, so you don't have to 1038 00:53:49,680 --> 00:53:54,170 answer the next two questions. 1039 00:53:54,170 --> 00:53:55,210 So OK. 1040 00:53:55,210 --> 00:53:57,080 So let's fix this. 1041 00:53:57,080 --> 00:54:00,130 And by fix it, I mean not use templates. 1042 00:54:00,130 --> 00:54:02,100 So now we're just operating on ints. 1043 00:54:02,100 --> 00:54:06,250 And ints do have the proper operator XOR that has all the 1044 00:54:06,250 --> 00:54:08,410 good properties that you want. 1045 00:54:08,410 --> 00:54:08,870 Yes? 1046 00:54:08,870 --> 00:54:10,660 AUDIENCE: What's the and notation of the variable. 1047 00:54:10,660 --> 00:54:14,030 PROFESSOR: It's a reference. 1048 00:54:14,030 --> 00:54:15,110 So it's a reference to it. 1049 00:54:15,110 --> 00:54:17,830 Because you need references, because you actually want to 1050 00:54:17,830 --> 00:54:21,110 swap the two items that are being called in. 1051 00:54:21,110 --> 00:54:21,380 Right? 1052 00:54:21,380 --> 00:54:23,060 AUDIENCE: Can you use like pointeres? 1053 00:54:23,060 --> 00:54:25,680 PROFESSOR: Yes, so you can also use a pointer for it. 1054 00:54:25,680 --> 00:54:29,210 Pointers and references, C will treat this use of 1055 00:54:29,210 --> 00:54:33,830 references the same way as if you use pointers. 1056 00:54:33,830 --> 00:54:36,480 So references are syntactic sugar. 1057 00:54:36,480 --> 00:54:39,400 And what it basically allows you to do is write code that 1058 00:54:39,400 --> 00:54:42,740 looks like you're operating on standard intervals, standard 1059 00:54:42,740 --> 00:54:46,630 integers, but in fact that it's a pointer to the value 1060 00:54:46,630 --> 00:54:50,290 that the name of the variable that's passed in here. 1061 00:54:50,290 --> 00:54:52,715 Otherwise this code would be riddled with a bunch of stars. 1062 00:54:56,600 --> 00:54:58,890 Now is this legal? 1063 00:54:58,890 --> 00:55:02,380 How many people say yes? 1064 00:55:02,380 --> 00:55:03,560 Most of the class. 1065 00:55:03,560 --> 00:55:06,870 How many people say no? 1066 00:55:06,870 --> 00:55:07,710 One person. 1067 00:55:07,710 --> 00:55:08,105 Yes? 1068 00:55:08,105 --> 00:55:10,228 AUDIENCE: If A and B are the same variable, 1069 00:55:10,228 --> 00:55:11,530 you set it to zero. 1070 00:55:11,530 --> 00:55:12,780 PROFESSOR: Yes, exactly. 1071 00:55:14,830 --> 00:55:19,310 The XOR law has a nasty side effect where you want to make 1072 00:55:19,310 --> 00:55:22,030 sure that A and B are not the same variable. 1073 00:55:22,030 --> 00:55:24,310 Not they don't contain the same-- they can contain the 1074 00:55:24,310 --> 00:55:26,830 same value in different variables, but they can't be 1075 00:55:26,830 --> 00:55:28,710 the same variable or the same register or 1076 00:55:28,710 --> 00:55:30,840 the same memory location. 1077 00:55:30,840 --> 00:55:34,920 Otherwise, when you do A equals Ax or B, that's 0. 1078 00:55:34,920 --> 00:55:38,000 And now both A and B point to 0. 1079 00:55:38,000 --> 00:55:41,240 And there's nothing you can do to get your old value back. 1080 00:55:41,240 --> 00:55:43,490 AUDIENCE: Can you check for equivalence of 1081 00:55:43,490 --> 00:55:46,400 recordkeeping in C++. 1082 00:55:46,400 --> 00:55:47,590 PROFESSOR: Indeed, you can. 1083 00:55:47,590 --> 00:55:49,750 If you take the address of the reference, it gives you the 1084 00:55:49,750 --> 00:55:53,160 address of the original value. 1085 00:55:53,160 --> 00:55:58,660 So this would be the proper way, I guess, of 1086 00:55:58,660 --> 00:56:01,420 doing an XOR swap. 1087 00:56:01,420 --> 00:56:06,090 So now that we've gotten over all the trick questions, is 1088 00:56:06,090 --> 00:56:08,920 this actually faster? 1089 00:56:08,920 --> 00:56:10,170 How many people say yes? 1090 00:56:12,940 --> 00:56:15,970 One, two, three, four. 1091 00:56:15,970 --> 00:56:17,220 How many people say no? 1092 00:56:20,730 --> 00:56:21,030 Cool. 1093 00:56:21,030 --> 00:56:22,180 Most of the class. 1094 00:56:22,180 --> 00:56:26,460 So this is another example of a gray area question. 1095 00:56:26,460 --> 00:56:30,750 So in this class, we primarily talk about the cloud machines, 1096 00:56:30,750 --> 00:56:33,130 as far as the performance analysis that we've done. 1097 00:56:33,130 --> 00:56:35,700 So on the cloud machines, and this was mentioned in 1098 00:56:35,700 --> 00:56:38,590 Charles's bit hacks lecture which was, well, the second 1099 00:56:38,590 --> 00:56:40,190 lecture in the course. 1100 00:56:40,190 --> 00:56:43,650 This trick is not faster on the cloud machines. 1101 00:56:43,650 --> 00:56:46,100 Because what you end up doing is you create a lot of 1102 00:56:46,100 --> 00:56:49,860 dependencies between these operands, so that the pipeline 1103 00:56:49,860 --> 00:56:53,120 must execute these one by one serially. 1104 00:56:53,120 --> 00:56:55,980 So you introduce a lot of delays by that. 1105 00:56:55,980 --> 00:56:58,790 And plus now that we actually want you to write a correct 1106 00:56:58,790 --> 00:57:01,270 program, you have to do this check, and 1107 00:57:01,270 --> 00:57:02,820 that's an extra branch. 1108 00:57:02,820 --> 00:57:06,210 And finally these XORs have to be done by the ALU, and up to 1109 00:57:06,210 --> 00:57:07,600 five execution ports. 1110 00:57:07,600 --> 00:57:09,040 Only three of them are ALUs. 1111 00:57:09,040 --> 00:57:11,750 The other two can do memory operations just fine. 1112 00:57:11,750 --> 00:57:15,270 So it turns out that for a combination of these reasons, 1113 00:57:15,270 --> 00:57:17,960 this version indeed with the temporary register actually 1114 00:57:17,960 --> 00:57:19,210 does run faster. 1115 00:57:22,360 --> 00:57:23,610 Any questions? 1116 00:57:26,537 --> 00:57:27,028 Yes. 1117 00:57:27,028 --> 00:57:30,219 AUDIENCE: For branches, we assume advanced features, like 1118 00:57:30,219 --> 00:57:34,580 it will preload the exceptions and only invalidates the thing 1119 00:57:34,580 --> 00:57:37,210 when certain branches fail. 1120 00:57:37,210 --> 00:57:39,650 PROFESSOR: Sure, you can assume cool properties about 1121 00:57:39,650 --> 00:57:42,270 the chip, such as speculative execution, 1122 00:57:42,270 --> 00:57:45,600 prefetching, and so on. 1123 00:57:45,600 --> 00:57:48,800 But the problem is those tricks are fine when you're 1124 00:57:48,800 --> 00:57:51,720 doing things sparsely as in you're sometimes doing work 1125 00:57:51,720 --> 00:57:53,280 and other times not doing work. 1126 00:57:53,280 --> 00:57:57,450 But like speculative execution, like when you 1127 00:57:57,450 --> 00:58:01,790 execute both sides of a branch, you're using more or 1128 00:58:01,790 --> 00:58:04,010 less double your execution or resources. 1129 00:58:04,010 --> 00:58:07,040 And if you have all processors running some intense piece of 1130 00:58:07,040 --> 00:58:09,970 code that's doing swapping, you don't have any extra 1131 00:58:09,970 --> 00:58:12,790 resources to dedicate towards running code that 1132 00:58:12,790 --> 00:58:14,040 might not be useful. 1133 00:58:17,430 --> 00:58:18,680 Any other questions? 1134 00:58:21,290 --> 00:58:22,400 Cool. 1135 00:58:22,400 --> 00:58:29,030 So finally, I got tired of making slides. 1136 00:58:29,030 --> 00:58:31,180 Well, actually that's not true. 1137 00:58:31,180 --> 00:58:33,640 It's more I'd rather concentrate the slides on 1138 00:58:33,640 --> 00:58:37,230 things that I think are more useful than other things, as 1139 00:58:37,230 --> 00:58:39,440 far as per preparation for your quiz. 1140 00:58:39,440 --> 00:58:41,230 All your time is valuable. 1141 00:58:41,230 --> 00:58:44,190 And so there's other topics that are fair game for the 1142 00:58:44,190 --> 00:58:46,680 quiz, because they've been mentioned in lectures up to 1143 00:58:46,680 --> 00:58:47,540 this point. 1144 00:58:47,540 --> 00:58:50,170 But I haven't prepared any slides on them. 1145 00:58:50,170 --> 00:58:54,870 And the fractal trees were covered by the guest lecture 1146 00:58:54,870 --> 00:58:55,870 by Bradley. 1147 00:58:55,870 --> 00:58:57,670 And the slides are up. 1148 00:58:57,670 --> 00:59:00,280 I suggest familiarizing yourself with the basic 1149 00:59:00,280 --> 00:59:02,450 workings of how the data structure that 1150 00:59:02,450 --> 00:59:05,630 he described works. 1151 00:59:05,630 --> 00:59:09,580 And lock free data structures were covered on your take home 1152 00:59:09,580 --> 00:59:11,930 P set, and also in a lecture. 1153 00:59:11,930 --> 00:59:13,940 So be prepared to answer potential 1154 00:59:13,940 --> 00:59:16,170 questions about that. 1155 00:59:16,170 --> 00:59:19,590 And then finally the mechanism behind the Cilk runtime, the 1156 00:59:19,590 --> 00:59:23,330 work stealing scheduler, how it's implemented on the Linux 1157 00:59:23,330 --> 00:59:27,580 side, and also the basics of what a Cilk hyperobject is, 1158 00:59:27,580 --> 00:59:29,850 what a Cilk hyperobject has to have. 1159 00:59:29,850 --> 00:59:33,970 Advantages and disadvantages of using them and so on. 1160 00:59:33,970 --> 00:59:34,650 Yes. 1161 00:59:34,650 --> 00:59:38,460 AUDIENCE: Are the grades for the P-set out? 1162 00:59:38,460 --> 00:59:40,750 PROFESSOR: No, they are not out yet. 1163 00:59:40,750 --> 00:59:45,260 AUDIENCE: Are there solutions for the P-set? 1164 00:59:45,260 --> 00:59:45,940 PROFESSOR: Not yet. 1165 00:59:45,940 --> 00:59:47,290 But I believe we have something 1166 00:59:47,290 --> 00:59:49,340 prepared for that, right? 1167 00:59:49,340 --> 00:59:50,590 Somewhat? 1168 00:59:53,100 --> 00:59:54,750 Yeah, it's somewhat prepared. 1169 00:59:54,750 --> 00:59:58,000 If you have any questions about like questions on the 1170 00:59:58,000 --> 01:00:02,560 pset that you want answer to, feel free to stop by office 1171 01:00:02,560 --> 01:00:07,190 hours or email us and we can help you. 1172 01:00:07,190 --> 01:00:08,940 Yeah, apologies for not getting that P set 1173 01:00:08,940 --> 01:00:12,110 back to you in time. 1174 01:00:12,110 --> 01:00:13,870 Any other questions relating to the quiz. 1175 01:00:16,480 --> 01:00:18,410 It's really all the material I have as far as reviewing. 1176 01:00:23,010 --> 01:00:23,500 Yes? 1177 01:00:23,500 --> 01:00:24,730 AUDIENCE: Are you going to put these slides up? 1178 01:00:24,730 --> 01:00:26,080 AUDIENCE: Yeah, I'll put these slides up 1179 01:00:26,080 --> 01:00:28,950 right after the lecture. 1180 01:00:28,950 --> 01:00:32,290 So as far as a general notes, I guess you guys turned in 1181 01:00:32,290 --> 01:00:37,855 your finals yesterday, and you guys have a design report that 1182 01:00:37,855 --> 01:00:39,190 you also turned in. 1183 01:00:39,190 --> 01:00:43,920 Your POSSE members should have contacted you by now, as far 1184 01:00:43,920 --> 01:00:47,550 as scheduling a design review session. 1185 01:00:47,550 --> 01:00:53,960 Since this project is actually due on next Thursday, it might 1186 01:00:53,960 --> 01:00:57,150 be a good idea to get this done by the end of the week. 1187 01:00:57,150 --> 01:00:58,780 Otherwise, the design review won't be 1188 01:00:58,780 --> 01:01:01,710 a very useful process. 1189 01:01:01,710 --> 01:01:04,530 AUDIENCE: There are a couple of students without a mentor 1190 01:01:04,530 --> 01:01:05,020 right now here. 1191 01:01:05,020 --> 01:01:06,630 We are fixing that. 1192 01:01:06,630 --> 01:01:06,950 PROFESSOR: Right. 1193 01:01:06,950 --> 01:01:09,570 There's a couple of students caught in limbo right now. 1194 01:01:09,570 --> 01:01:11,960 Sorry about that. 1195 01:01:11,960 --> 01:01:18,360 PROFESSOR: If you were-- previously dropped on Stellar, 1196 01:01:18,360 --> 01:01:20,972 send us an email. 1197 01:01:28,370 --> 01:01:31,471 If you haven't been to drop through this course, there are 1198 01:01:31,471 --> 01:01:33,420 no longer drops allowed. 1199 01:01:33,420 --> 01:01:33,710 Yeah, 1200 01:01:33,710 --> 01:01:36,520 AUDIENCE: So it's your responsibility. 1201 01:01:36,520 --> 01:01:37,850 I'm going to put on my mean hat. 1202 01:01:37,850 --> 01:01:41,350 It's your responsibility to schedule a meeting with your 1203 01:01:41,350 --> 01:01:44,670 POSSE member, and make sure that it happens by 1204 01:01:44,670 --> 01:01:45,480 the end of the week. 1205 01:01:45,480 --> 01:01:47,525 And if it doesn't look like it's going to happen, or 1206 01:01:47,525 --> 01:01:49,310 you're having difficulties getting in touch with your 1207 01:01:49,310 --> 01:01:53,080 mentor, or you don't have one yet, please drop us an email 1208 01:01:53,080 --> 01:01:56,820 or come by office hours and make sure that we know. 1209 01:01:56,820 --> 01:01:57,390 All right. 1210 01:01:57,390 --> 01:01:58,640 That's it.