Hello everyone, and welcome to this session on host performance booster. Before we move, let me introduce myself. I'm Aleem Akhtar, working for Samsung Semiconductor India Bangalore. I'm also one of the reviewer of Linux UFS subsystem. Let's have a look on today's agenda. So today's agenda looks like this. So we have divided this agenda into two half. The first part I am going to cover about the basics of UFS and its transaction. And that is important to understand HPB. And in the second part, my colleague Jim Young will cover what is HPB, why HPB. And he will also walk us through its implementation in Linux kernel. And then we will have a look on some of the performance improvement data with HPB. And at the end, we will walk through the current mainline support status. Okay, so let's move forward, technical background. As we all know, UFS stands for universal flash storage. And this is a simple high performance mass storage device with a serial interface. And it's provide high performance and low power consumption. These days, these are widely used in commercial embedded product like smartphone or any other embedded product which need a high performance storage device. Inside Linux, UFS implemented under a quasi subsystem. Before we move forward, let's see where UFS stand in terms of read and write comparison with EMMC. So as you can see in this table with the EMMC 5.1 sequential read is around 250 megabytes per second and write is around 125 megabytes per second. In case of UFS, the read is around 2100 megabytes per second and sequential write is around 410 megabytes per second. So we can clearly see there is a 8.5x jump in read performance and 3.5x jump in write performance. And no wonder why these days all premium smartphones are coming with UFS as an internal storage. Let's move to the next slide. So this is the top level architecture view of UFS. So UFS communication is a layered communication architecture and it is based on Kazi SAM architecture model. So at the top of it we have an application layer which contains UFS command sets and UFS command sets contain UFS native command sets as well as simplified Kazi command sets. And this layer also contains a task manager and a device manager. The next layer of UFS is UFS transport protocol layer or we call this UTP layer. So this layer is responsible for all the transaction in and out of UFS. And the last layer is UIC layer we call interconnect layer which consists of a MIPI unipro protocol as well as MIPI M5 as a physical layer. Let's move to the next slide. This is the overall UFS system model. So you can see like it contain a host and a device and the host and device are connected over UIC layer and host on an application which talks to UFS driver, which is the protocol driver, and then it's stuck to a low level controller driver. The low level controller driver is also called as HCI like host controller interface, which basically expose register sets for the UFS protocol to communicate. So this is a view on how things are arranged in Linux. So within the kernel we have a file system where like application make a request to a device file, and then it goes to block layer and then I should learn. And then it's goes to cousin here and from cousin here it goes to UFS driver and then through the low level driver stock to UFS device. So if you see the overall code organization in the Linux, so driver cousin UFS contains the entire code, including the protocol and the low level driver. So protocol driver is actually inside single file called UFS hcd.cnh and rest of the files are supported low level drivers. Move on to next. So host and transaction in UFS. So as we talk like UFS is a layered protocol, and it is based on fuzzy Sam model. It is also a client server or a request response model where a whole system act as a client, and the target or the device act as a server. So the request and device or the target respond back to the request and all UFS transaction consist of packets called UFS protocol information unit or UPIU. UPIU contains a single constant 12 byte header, a transaction specific segment, possibly one or more extended header segment, and zero or more data segments. So this table list all the UPIU that is supported in UFS. Like we have a command UPIU response UPIU task management UPIU and task response UPIU and so forth and so forth. So all these UPIU contains a single constant 12 byte header, and the transaction code indicates what kind of UPIU it is. Now let's understand how the flash storage work. It is important to understand the rate latency inside the UFS device. So all NAND flash devices use something called FTL or a flash translation layer to translate logical address of IO request to flash memory physical address. Like logical to physical or we call L2P mapping entries are managed by FTL. This is similar to CPU virtual address and the physical address where MMU do the translation of a virtual address to physical address similar to that all logical IO request will ultimately get translated into a NAND flash physical address. And this also have a translation entry or mapping entry that is generally stored on NAND flash memory. So normally all UFS devices have a small SRAM to cache this entry or the recently used entry to speed up the performance. But because of the high cost the size of the SRAM is very limited so we cannot cache all the mapping into SRAM. So this is causing some latency in the lead and in the next slide we'll see what it is. So this is the overall concept where the lead latency is coming into. Right, so let's take this example where the UFS device has fetch a read command from the host controller. And then it request for L2P entries. Since L2P entry is not cached into the SRAM it has to go and load the entry from the NAND flash itself which is going to add an extra latency. So which is depicted by TR map in this right hand side diagram. Right, so we are going to address this read latency issue with a concept called host performance booster. And this concept is going to cover by my colleague Jomin in the next part of the presentation. So with this I'll hand over the presentation to Jomin. Okay Alim, thank you for sharing a good instruction about UFS. So from now I'll take a turn and I will introduce the host performance booster, also known as the HPB. Before I start the section, please give me a time to introduce myself. Hi, I'm Jamio. I'm working with Samsung since 2018 as a device driver engineer. And now I'm developing and maintaining the extended feature of UFS driver. I'd like to say thank you for sharing your time to this presentation. Okay, let's go back to slide. The next section is the introduction of HPB. Through this section, we find out the overall concept of HPB. What is HPB? What does it do? How? And why should we know about the UFS and its architectural design to understand the concept of HPB? So let's go through the first slide of this section. What is HPB? The host performance booster is an extension feature of UFS subsystem. The purpose of this feature is to improve the overall performance of UFS device through reducing the read latency. The HPB is defined as an extension specification of JDAC UFS 3.1 standard. Its pack document can be found on JDAC website, so I added a link at the bottom of the slide so you can check it after the end of the presentation if you want to know further. So now we know what the HPB stands for. Then let's talk about the concept. In the previous slide, we mentioned that the HPB improves the performance by reducing the latency. How does the HPB reduce it? It works with simple idea. The HPB supports caching the UFS device's mapping entries in host memory. The HPB operates on the host side, so in Kono, it can locate and access the host memory without any additional procedure like DMA or bounce buffer or something like that. Even in the embedded system, the host memory is still big space enough to cache the mapping entries of UFS device. The portal mount of the system's host memory continues to grow today. Also, accessing the random access memory is still quite faster than accessing the landflash memory of UFS device. Of course, you can worry about the host memory usage, but are the mapping entries big enough to degrade overall performance of the system? Let me calculate the actual usage. So let's assume that the UFS logical storage space with a total capacity of 128GB. In general, the UFS manages its internal storage space with 4KB logical block size. Therefore, there will be about 33 million blocks in the total space. It sounds a lot, but we should know that the HPB caches the mapping entries only. Through the specification, the HPB allows 8-byte address information as a mapping entry for its logical block. So, the total memory usage of mapping entries will be 8 multiplied by 33 million bytes. So, it will be 256 megabytes. So, we can see the caching all the mapping entries for the 128GB total storage will only use the 256GB host memory space. And also, the actual usage will be even lower because the HPB doesn't cache all mapping entries of storage on the host memory in normal use case. In this slide, you can see the brief call path of the command operation in UFS device and the lead latency when the HPB is applied. As you check the lady, the UFS has an additional lead latency because of the then flash memory characteristics. If the mapping entry of requested data is not cached in internal SLAM, the device must read the mapping entry from then memory first. But, in this case, the HPB is included in the UFS driver and it operates. The HPB checks the host memory first when the read command is requested. If the required mapping entry is cached already, the HPB transfers the mapping entry with the command to the device. Therefore, the device can access the physical and cell of requested data directly. So, at the right side of the slide, you can see the differences of lead latency of UFS device between with and without HPB. You can see the device can eliminate the additional lead latency of then access duplication with support of HPB. So, as a result, the total lead latency of the device will be reduced. So, now we understand the overall concept and behavior of HPB. So, from this slide, I will explain a little bit more. I will explain the overall behavior of HPB in chronological order. On the left side of the slide, you can see the mapping entry which is located in the host memory. The HPB manages the logical space of UFS device by dividing them into specific size. This is called the HPB region. Mapping entries within a region and region itself are logically contiguous. Then, you can see the abstracted data structures of HPB in the middle. The mapping entries for region number 0 is already cashed by HPB, but the mapping entries for region number 1 is not. Also, you can see the state of region number 0 as region number 1 in the HPB region lookup table. The state of region number 0 is valid, but the state of region number 1 is invalid in this state. So, it is the initial state of the slide. Let's assume that a new scarce command is issued from the host to logical storage space which is described by region number 1. The driver sends a command to the device as normal and the device will return a response at the end of the transaction. In this case, the HPB doesn't do anything because there's no mapping entries is stored in the host memory for region number 1. Then, the HPB requests the first mapping entry of region number 1, the device, through the internal request issuing. When the issued request arrives at the device, the device passes the first mapping entry for region number 1 to the driver as a request completion. Then, the HPB is towards the mapping entry in host memory. In this picture, you can see the mapping entry which is highlighted with blue color is stored in the HPB entry table for all the region number 1. Then, the HPB is operated on the provision basis. As a result of that, the HPB sequentially requests all mapping entries in the region to the device. And, when all mapping entries are cached in host memory, the region state will, in local table, will be changed to valid. From now on, the HPB can support mapping entries in the read command that requests the data in the logical storage space which is described by region number 1. Then, the read command is requested the data which is stored in logical space which is described by region number 1. When any of the read command is requested, the HPB checks the validity of the region. In this case, the reason for requested data is valid. It means that the every mapping table in the region number 1 is ready to go. So, the HPB access the read the cached mapping data, cached mapping entries in host memory. Then, the HPB changes the request read command to the special command. It is the HPB read command which contains the cached mapping entries inside the command configuration. Afterward, the HPB finally issues the request, finally issues the request which the command is changed to the HPB read the device. Mapping entries are passed along with the HPB read command and it allows the device can access them and sell of requested data directly. Okay, so, through the previous slide, we now understand the overall concept and overall behavior of HPB. So, from next session, we will take a step forward to a little bit more and a little bit deeper. It means that we will see the actual implementation of HPB in Linux kernel. It contains the data structure, state model, and more detailed behavior with architectural specification of HPB. So, to understand the HPB implementation, we should check the data structure first. As I explained already, the HPB operates as a part of the UFS driver. So, the UFS driver has the HPB related device information as a part of its internal data structure. It is stored in UFS HPB device information data structure. It includes the number of logical units which the HPB feature is activated with and the size of its region and sub region and the other information. This information is used to initialize the HPB and allocate the cached space from the host memory. Another data structures of HPB are defined in the HP code inside. Let's check the UFS HPLU first. It is the main data structure which contains the data of the whole internal information of HPB, logical unit number, region table, which describes the whole region of HPB, and HP state. Also, it has the LRU info data structure either. It is used for cache management. You can see the UFS HP region and UFS HP sub region data structure. Each of it describes the region and sub region of HPB. Each region and sub region has its own state and index number table. Each sub region has a UFS HP map context data structure. It describes the actual mapping entry of each sub region. All the mapping entries of HPB are stored in pre-allocated memory pages in UFS HP map context. Of course, there are still more internal data structures in HPB, such as the UFS HP Recast data structure, which is used for internal command requests. But it is not in the scope of this presentation, so those are not included in this picture. So for further information, please check the definitions in HP header file. So the next slide, you can see the internal state change of HPB itself and its region and sub region through the whole lifecycle. HPB is initialized when the UFS driver is started and it enters the HPB state. After initialization is completed, it changes to HP present state. If the initialization process is failed or an unrecoverable problem occurs, the HP enters the HP failed state. It means that the HP will be deactivated. Even in this case, the UFS behavior itself is not affected. Also, depending on the whole system's own reset signal or power management process, the HPB can go to the HP Suspense or HP Recess state after the end of the process. And it will go back to the HP present state. So each of and every region and sub region of HPB has its own state. Immediately after the HPB initialization, all non-fin regions start in inactivated state. If the region is subsequently activated, the region will be in the HP region active state. And when it is deactivated again, it returns to the HP region inactivated state. Then the HP supports the special regions if it is needed, the pinned region. The pinned region does not change through the whole lifecycle. This region is activated in this region is activated in initialization process and it will never be deactivated. It means that the UFS logical unit space which is described by those pinned region mapping entries of it always cast in host memory. So the origin is made up of several sub regions. When activating, the entire region is activated in units of the sub region. Our sub regions in an inactive region are in the unused state first. And then when a region is inactivated, all sub regions in this region changes to the invalid state first. And then while the mapping entry of the sub region is recasted to a device, the sub region of the mapping entry, the status changes to HPB sub region issued state first. And then after the mapping entry is normally recieved to the device and it is stored in host memory, the status of it goes finally HP sub region valid. So the HPB check the status, use the status to check the validity of the mapping entry when the read command is recasted. So HPB decide to change recasted with command to the HPB read command which includes the mapping entry inside. When the HPB state is when the HPB state is HP present, the region state is active for PIN and also the sub region state is valid. And then the HP check the check the big map of the validity of mapping entry itself. So the mapping entry itself should be clean. So, then why is the mapping entry could not be used even if those all state are valid? I mean, why some of the mapping entry becomes dirty? It is because of the write and discuss command. If those command are recasted to the user data, which is mapping entry of it is already cached, the HPB directly set those mapping entries for those data as dirty. So, now we know the HPB manages the mapping entries in cache. Then, who decide to let the HPB manages those caches and manages those mapping entries? The whole system or the user application or the HPB itself? Actually, the device does it. Let's remember about UFS itself. Alim gave us already the good explanations about data transactions of UFS specification. It operates as a server client model. It means that the each single transaction between host system and UFS device is a set of UPI packet, which include one command UPI as a start and one response UPI as end of transaction. The UFS device, which support the HP feature, gives an information for each cache management to this response UPI. The picture on the right side of the slide is the configuration of response UPI in JDAC HP 2.0 specification. You can see the number of active server region information and inactivity region information is included in the end of response UPI. The HPB is inactivated in unit of, sorry, so the UFS device sends those HP cache management information in the response UPI when every single transaction is happened. And then the HPB accepts those information and manages the mapping entries in the cache through this information. So you should check that the HPB is inactivated in unit of sub region, but it is activated in unit of sub region. I'm sorry, the HPB is inactivated in the units of region, but it's activated in the unit of sub regions. So, in this slide, you can see the how the HPB activates the region which has the sub region which is informed by device. First, the normal IO is requested from the user application. It goes all the way down through the file system, log layer, IOS cache layer, then finally reaches the UFS driver. In this layer, the HPB can access the information of request inside. Then, you check the mapping entries for the request are cached. If the entries are not cached or the mapping entries are not valid, it decides to test the request to device without any modification. Then, the UFS device informed to activate the sub region through the responsive PIU. In this timing, the HPB is worked as an interrupt context. So, it just adds the informed sub region into active list and schedule the worker. The worker will start it at the process context later, and it will recast the request for command to the driver to recast the mapping entries of prison. After the completion of it, the HPB stores the mapping entries in host memory and ready to recast the HPB. The HPB sends the cache mapping entries as a part of HPB's command. But, if the transfer length of the request with command is bigger than 36 kilobyte, the whole mapping entries cannot be included in one HPB's command. In this case, the HPB sends the writeable command as a prefacing command with mapping editor is needed, and then sends the HPB command after. So, in this picture, you can see the readable command and writeable command is the first time to check the internal request of HPB. So, the HPB uses readable command to recast the mapping entry to device and uses cache writeable command to as a prefacing command internal. But, it is not the, not in the scope of this presentation, the internal request issuing. So, if you want to more information about it, please check the specification documentation of HPB to the JDAG. And then, you can see the additional management, the inactivity. In the normal use case of the HPB, the whole number of possible activity region is smaller than the total regions of our storage space. It means that the cache size is smaller than the total size of our mapping entries of the storage. In this case, some of some of activated region can be inactivated at any time. There is two possible cases of routine activation. The first case is when the new region activation is formed by device, but the cache is already full. It means that there is no space remain for the activation. The HPB manages all active region with LRU algorithm. To this scheme, the last region on the list, which is the list recently used region, will be selected as a victim. So, the HPB removes the selected victim region from the list and inactivated to make a free space. After that, it activates the new region. In this case, the total number of active region will not be changed. But the region can be inactivated even there is enough space in cache. This is the second case. The device can inform the exact region which needs to be inactivated as a result of the device internal operation. Sometimes it could be a garbage collection and sometimes a defragmentation or the result of internal hard-coded FTL algorithm. So, after the information arrival of the region inactivation, the HPB finds the informed region of LRU list. And then it deletes the region directly from the list and inactivated. In this case, the total number of active regions will not be reduced and will be reduced. Okay, so through the previous section, now we understand the detailed behavior of HPB at each implementation. But there's still one other question. Is it really works well and the performance is improved as intended with HPB? So, we will show the measured performance improvement through this section. So, in this section, the quantitative performance result of UFS device and HP applied device are shown through the graph and table. Through this comparison, we can confirm the actual effect of HPB and overall improvement on read command. So, in this slide, you can see the benchmark and user experience result comparison. Let's go to the picture on the left side. In this benchmark result, you can see the change of throughput of UFS device with and without HPB. In the one-year-old range result, there's no big difference between two results. It means that the almost every mapping entries of read command occurred is cached in internal device SRAM and heat rate of it is quite good enough in small high-range. But as the high-range increases, the performance of UFS becomes decreases. It means that the cache miss has happened more in bigger high-range environment. But the HPB can see the increasing the IO range does not decreases the performance of UFS device. It means that the more mapping entries are cached in host memory with HPB, so cache miss isn't happened a lot even with large IO range. So, then let's go to the next table. It shows the changes of lab run. It shows the changes of lab run at lunchtime as each cycle increases. A cycle means the amount of time usage which is spent to launch the set of predefined applications sequentially. The difference in the time required between those two cases increases as the cycle increases. This means that the longer the storage device is used, the greater the performance gain through the uses of HPB. So, in the next slide, include the more detailed chunk range measurement result. This graph shows the performance change of UFS device with and without HPB, according to the chunk size of the read pattern. The performance improvement is most noticeable in small chunk, and the performance improvement gradually decreases as the chunk increases. But, you can still see that the HPB improves the read performance compared to conventional in all size of chunk. So, through this benchmark user experience and chunk range result, we can confirm that HPB actually improved the read command, actually improved the performance by reducing the read command, and it works well. Now we understand the HPB in general, and we have also confirmed that this idea actually works well. Me, Alim, and my other colleagues who actually developed the current HPB thought this idea was quite reasonable, and decided to open this code implementation and overall idea as open source. So, in this chapter, I want to share what has happened and what is going on with HPB. So, let's talk about the status of HP upstream on this mainline first. The HP upstream has been started in second quarter, 2020, and now the patch version 40, which supports the HP 2.3 specification is committed to the current SCAR subtree by the June Park, and the host control mode for HP, and the host control mode for HP is also proposed by every alternate WDC. So, below is a list of people who contribute to create the current mainline HP code, and also there's lots of people which is not enlisted and they are still review, they are still help and support the HPB to review, recommend, suggestions, and lots of their effort they can do. I'd like to say thank you for your ideas, suggestions, tests, and patches. Thank you. So, next slide, you can see the timeline of important event that occurred during the HP upstream process. So, left side, on the 18th of March, 2020, the microphone posted the first HP code, which follows the HP 1.3 specification on the mainline. This is the first event that happened with HP on mainline, and after more than one year, the HP merged as AOSP under the open source project, and also it is committed as a Linux SCAR subtree. So, I'd like to, I don't want to list every event on the timeline in Word. So, if you want, if you want to know more detailed history, please check patches and commands on Linux SCAR subtree. So, this is the last slide. Through this presentation, we saw the overall operation and implementation and ideas of HP, and also we saw the process of being incorporated into the open source project and open source itself and current status. The HP is like all other open source code is constantly changing. Still now, HP, which was first posted last year, has now been patched up to version 40. It means that HP is still alive. So, there has been many, many suggestions with HP, which are included in the current HP mainline code. So, please contribute it. It is the main purpose of this presentation. We decided to introduce HPB to the people who is a part of open source community to encourage the people to participate in. Please review it, test it, share the bug and fix it you found. We will appreciate for your joining. Thank you. Ah, if you have any questions, feel free to ask them in Q&A session after this presentation. Me and Arlim will do our best to answer all your questions as we can if you have enough time. Thank you.


The G5 governors of the People's Democratic Party stormed Ibadon-de-Yosé capital to support one of their own in campaigning for a re-election in the state. The group also reiterated their resolve to make public their choice among the presidential candidates vowing in the February 25 election. Our correspondent has more in this report. It is a total display of solidarity as members of the Integrity Group converge on the ancient Macbu All in Ibadon to support their own governor She'i Makin dey for his re-election bid. The governor of Enugu State, Ifa Nyu Gwaini, and his Abia State counterpart, Okezi Ikwazu emphasized that the Oya State governor represented a vision for a better Nigeria and desires a second term in office in the state. For the governor of River State, Inyesom Weke and his Benwe counterparts, Samuel Othom, the long-awaited communication on their preferred presidential candidate, would be made known soon. The governor of Ibadon, Okezi Ikwazu, and his Abia State counterpart, Okezi Ikwazu, would be made known soon. The governor of Ibadon, Okezi Ikwazu, and his Abia State counterpart, Okezi Ikwazu, and his Abia State counterpart, Okezi Ikwazu, would be made known soon. The man of the moment, She'i Makin dey, promised to improve on critical sectors of the state's economy if given the opportunity to serve again. The G5 governors maintained their loyalty to their party, the PDP, calling on Nigerians to support her in the coming elections.


The 2019 novel coronavirus disease emerged in China in late 2019 early 2020 and spread rapidly. China has been implementing emergency psychological crisis interventions to reduce the negative psychosocial impact on public mental health, but challenges exist. Public mental health interventions should be formally integrated into public health preparedness and emergency response plans. This article was authored by Lu Dong and Jennifer Buie.


In this episode of Lifespan News, you'll find out why quality sleep should be part of your longevity strategy. More evidence that nicotinamide riboside supplementation provides health benefits, and more evidence that intermittent fasting provides health benefits. You'll find these stories and more in this episode of Lifespan News. Welcome to Lifespan News on X10, your source for longevity science updates. I'm your host, Brett Nally. We encourage you to check the description below for links to these stories. For our first story, according to a new study, poor sleep quality may be a major factor for developing Alzheimer's disease and other dementias. It was already known that poor or insufficient sleep increases your risk of various chronic conditions such as heart disease, diabetes, stroke, obesity, and kidney disease. But the authors of this new study wanted to figure out the link between poor sleep and the risk of developing dementia. The researchers used data from an ongoing study of older U.S. adults. The National Health and Aging Trends Study, or NHATS, which followed participants for five years and it was found that people who reported having less than five hours of sleep a night had doubled the risk of developing dementia than people who slept seven to eight hours a night. Also, people who took longer than 30 minutes to fall asleep once in bed had a 45% increased risk of developing dementia. Daytime sleepiness and insufficient sleep was also linked to increased mortality. Given the importance of good sleep, you should do what you can to ensure you get the right amount of quality sleep. A few things that you can do to that end are avoiding light from devices before bedtime, avoiding stimulants such as caffeine in the evening, and keeping your bedroom to a comfortable temperature. As we reported on last week's episode of Lifespan News, Lifespan.io has recently launched a crowdfunding campaign to support longevity research by funding a large human trial called the Participatory Evaluation of Aging with Rapamycin for Longevity Study, or PERL. Lifespan.io will host a live Ask Me Anything on Reddit with the PERL team from May 30th to May 31st, 2021. We will accept pre-questions for this AMA from May 28th to 29th, 2021. The AMA URL won't be available until May 28th, so be sure to check the link in the description below on May 28th. Of course, you can check the link in the description below before May 28th to learn more about PERL and make a donation. For our next story, nicotinamide riboside rejuvenates blood, stem cells, and researches have reversed the age-related decline in the function of hematopoietic stem cells, or HSCs, in older mice using nicotinamide riboside, or NR, which is a precursor to the important mitochondrial activity regulator NAD. NR was already known to boost the function of young HSCs, but the team wanted to know if this also happened for older HSCs. So the researchers gave mice an eight-week course of NR, which made the old HSCs more quiescent, reducing their metabolic activity and increasing their proliferative potential. NR also led to the clearance of defective mitochondria and a decrease in mitochondrial stress markers. Transcriptome analysis showed that gene expression in old HSCs treated with NR became more similar to young HSCs. Unfortunately, the effects lasted only for as long as the NR treatment was administered. As soon as NR supplementation was discontinued, HSCs quickly returned to their age phenotype. This research shows a possible way to reverse HSC aging and contributes to our understanding of the important role NAD plays in cellular metabolism and in age-related disorders. Since NAD precursors are largely safe and widely available, every piece of new evidence of their rejuvenating activity has substantial importance. By the way, Lifespan News is released every Tuesday at noon eastern time, while our other Science and Advocacy X10 videos are released every other Monday also at noon eastern time. For our final story, intermittent fasting changes the composition of the gut microbiome according to new research. An increase in the abundance of a group of bacteria known as lachnospiracy may explain some of the health benefits linked with dietary restriction. To investigate intermittent fasting, researchers in China and the Netherlands took advantage of the fact that many Muslims voluntarily refrain from eating between sunrise and sunset during the Islamic lunar month of Ramadan. The researchers measured changes in the gut microbiome and physiological metrics in two age cohorts of men who were fasting during Ramadan. The researchers reported a quote substantial remodeling of the gut microbiome and quote in both cohorts. The researchers note as especially important an increase in lachnospiracy as a result of fasting and this increase correlated with improvements in physiological markers such as blood glucose and body mass index. The increase in lachnospiracy and the improvement in physiological markers both disappeared after fasting stopped, meaning the effects were reversible rather than long term. Because lachnospiracy produce butaric acid which is known to provide metabolic benefits by affecting the brain gut neural circuit and has been linked with other health benefits, the researchers speculate that the increase of lachnospiracy may be an important factor in the health benefits of intermittent fasting. That's all the news for this video. Is there a recent life extension story that we haven't covered yet that you think we should have? And what was your favorite story from this episode? Let us know what you think in the comments below. We really appreciate it and we look forward to seeing you in the next episode at least as healthy as you are now.


So this kick streamer assaulted his girlfriend and then destroyed her gaming set up. Here's what happened. I was in the gym listening to Tiffay stream when she read this comment out loud. My friend's boyfriend just destroyed her set up. I immediately stopped my set and then messaged that person to send me their friend's information. They gave me the discord of the girl who set up was destroyed and I left a message saying your friend showed me what happened, I wanted to ask if you were okay. After a few days she explained that her computer would turn on but there would occasionally be errors and that both monitors were completely destroyed. First I asked if she was safe and then offered to replace the monitors. Afterwards she sent me a video of her boyfriend who left his stream on, proof of him coming in and destroying the set up. I'm not going to show the rest of it for obvious reasons. So why am I showing it in the first place? Well I actually drove down to LA this past month to surprise her with two new 240 Hertz monitors. I'm sorry about what happened.  No you're sorry. I really appreciate it. But that's not all I want to do. I just want notifications to learn how you can help with what we are going to do next.


Hello everybody and welcome to another hobby cheating video and today. It's finally time. Let's paint up the big boy himself The big bad It's time for Horace Ascended. Let's get into it Let's strict techno man sir that is Vinci V. Let us get to the technique and learn it Vinci V style If you've been watching the channel the past couple weeks You've seen me do a little bit of painting on Horace You've seen me prepare him and get the resin ready Today, we're going to go through the whole painting process I'm going to take you through painting Horace Ascended how I attack it why I attack it the colors I choose where I place them basically we're going to do the whole model from top to bottom This guy is a really really cool model. I really dug him as soon as I saw him I knew I wanted to paint him So let's get over the desk and get into it the paints are going to scroll up top for you as we're going here And if you watched the previous video where I introduced the new signature series of paints I partner with Monument to bring some of these clips will be a little familiar here at the beginning But we're going to go into more detail and we'll breeze through some of this pretty quickly The idea here at the beginning is to start on the black armor It's a pretty important core element of this guy though. It is less of him than I would like I'll be honest He's got a lot of stuff all over him, but I want to add some real infusion of tones Black armor will still read as black as long as about 50% of the surface that you're painting is actually still black You can have really bright reflections other colors that aren't in there If you've ever seen a shiny black car driving down the highway Well, a lot of there's actually a lot of white and gray and reflections of the trees and sky and things like that But you still easily recognize the surface as black So as long as about half of the surface is still in black tone, you'll be fine And when I soften everything up here with the airbrush I'm really just wanting to still preserve some of those colors and those tones underneath While diminishing somewhat of the the color travel. So it's not going quite as far Now when I move on to the cloak and and you might ask why am I working from black? Why didn't I zenith or something like that? I have some very specific lighting elements in mind and so instead of Doing a general all-over highlight diffuse highlight I wanted very specific placed highlights as a result I'm working up from black to preserve all my deep shadows between everything and be able to set my colors individually So these next steps are really just base coating these individual things laying down that dark plum on the cloak and now building up the wolf now in the Box art the original art the wolf is actually quite Dark, but I didn't like that as much I wanted the wolf to be a little more bright A little more white to sort of draw more attention to the top of the figure And this is one of those things where how you balance the colors and the intensity and the value On your miniature can often have a big impact on its readability You generally want the brightest areas the things that are going to draw the most attention That are also the warmest to be up around the head area effectively where you want your Viewer's eye to land and to look the first place people look is the head If you place really bright colors in the area around it in a sort of halo as this wolf's fur does It will help to instantiate that and draw that effect Now this is helped by the fact that Horace has a red glow inside his armor and human eyes track to the color red So, you know extra benefit I guess With the wolf done I then turn to you know building up the actual cape And here I take multiple passes with the airbrush and the important part with this is I'm using The shape of the cloak to do a lot of the work for me So that is to say I'm working you know at these angles where the airbrush isn't going to hit those lower recesses And then working progressively smaller and smaller areas Building up to that intense full royal purple and then eventually integrating in some of the Colder blue into that as well to give it this nice royal luxury a sheen This is another one of those things where in the art His cloak is red, but I like it better as purple purples the color of royalty and Horace imagines himself a You know a would be king I suppose Then we turn to a bunch of little details and boy is this guy full of bejangles I mean he is the king of bejangles But really it's just laying down base coats on all these And then seeing how it looks once we have all of them in place Remember when you're placing these initial colors Sometimes these things might seem too bright or too dim But that's because I left the metallics for last now once the metallics get on there later in the paint job It's going to really change the way the whole thing looks They're going to be so bright so shiny that they'll make some of these very bright things actually look quite a bit darker by comparison So you'll have to often go back and readjust your work at the end Don't ever feel bad about going back and forth in an area or painting on something Bringing an area to 80 90 percent and then reattacking the rest of it later. That's not bad That's just standard painting and in fact when you're doing display or competition painting The reality is you'll go back to those areas two times three times five times ten times to continually adjust them And that's okay All right, let's work on the face for us for as big as he is his head is not that much larger than a normal human's head Which I suppose is probably somewhat appropriate. He is still a normal human or well He's a human at least or was But at any rate I'm working in a lot of like red and pink tones to start and that's because I want to build this up He has this very warm skin tone because of the red Underglow this sort of light from below this light from hell that's on his armor And so I want that to be infused into all of the tones until I get up into the very highest highlights And shift it over into the yellow tone, which will be the reflection of the sort of fiery battle around him As a result it's I I'm slowly subtracting out the pink and infusing in more yellow influenced tones like warm flesh And things like that as I climb up And I'm also using sort of a Rembrandt style lighting here Which just means I'm focusing most of the light to one side of the face and from slightly above and then hitting that upper cheek On the opposing side of the face This will give me a lot of room to play with the counter glow of the red shooting up And since he's facing to his left in the actual miniature once this head is placed in It'll then sell that color in that effect really nicely My last step in this particular phase with the face Is to get nice deep magenta tones in there under the eyes and the lips And down at the lower part of his face pretty heavily on the left side Where it's going to be really influenced by that glow now again. This isn't the glow itself. This is just prepping for it Speaking of orange and yellow lights from hell. Let's talk about his little eyes of Horus here or whatever With each of these they were very simple. I just started by Covering them all in a nice ivory tone and then once that was done. I then build them up So but in sort of reverse instead of building toward the top I build toward the bottom So starting with that yellow and then working into more orange yellows and finally into the fluorescent orange pulling all the colors down toward the bottom Working in very very very thin glazes with all of these all these paints are highly transparent already oranges and yellows And then I'm working in just thin glazes of them multiple applications so that I get a nice smooth application of You know of the actual tones and don't have to go back and do any extra work a few quick layers and we're good Now I'm setting some of the edge reflections and since I had that fluorescent orange This is why I decided to do this so I pop out things like the edges in that fluorescent orange mix with just a little bit Of the red not because I intend to keep them like that but because I'm doing that as an under shade for later Speaking of that red glow I load some of that up in the airbrush and then just very quickly shoot that up at this low angle At his face and I'm working the angle and it might look a little strong here But that's just because the paint's wet and shiny once it dries down It's not going to be bad at all. It'll be exactly what we want I do end up working a little on both sides of the face He does have the red glow coming up all around his head But we're focusing a lot more heavily on his right side the side that will be more exposed to the viewer Um, and then I go back with a little 50 50 mix of my warm skin tone and that red tone And just kind of smooth out with a quick simple glaze between those two areas Again, I want the red glow to feel like it's coming up from below And then naturally transitioning into the ambient environmental light of the battlefield With all of those basic lights and edges and colors and tones in place We then turn to the most annoying part of the figure Which is the base coating of all of these metal edges and more Just so many metal edges on this guy It just keeps going and then of course even more even his cape has these Now oftentimes I don't recommend doing true metallics on cloth. I think it can kind of look weird But these were so pronounced like they're so raised off of the cloak that I felt okay doing it and like it just would Fall in line with this sort of edge pattern of the armor itself But he's not all gold Between his little studs in his armor And then these pistons and such that I assume are in the power armor helping him move and change Those are also there, but we can't just straight apply the metallics The next most important thing and what I want to do here is make sure that the lighting of the metallics Matches the lighting that I've set up on the matte areas And that means applying these tones these brown tones these matte paints And then into purples Into these areas to create shadows to matte out the reflections And this is a really important step There's a bit of non-metallic theory in here as to where you want to place these particular shadows in this case I'm placing the shadows just wherever it matches the lights I've done on the matte armor So in other words if I said there was a reflection in the matte armor Then I made sure there was a reflection there in the the metal as well If I said that area was a shadow I painted it as a shadow and so on and so forth Just making the metallics match what I've already said is the lighting situation With the actual matte paints that helps bring it all in line There's not a ton of silver as I mentioned just like his claws and a few chains And though normally I'm quite against washing metallics because it makes them look a bit dirty and dull I actually thought that was appropriate for this battle-worn claw Like I imagine he stabs and kills quite a lot of people with these So I didn't think it would look too rough or sorry too, uh too shiny and new I thought it would look quite rough and besides I go back of course after that And clean it up focusing mostly on the edges that would be glinting very brightly Now we're going to turn to that actual red glow the the red inside his helmet And the important part to sell this is to pick a direction and cast that light In this case, I'm assuming it's casting from his right your left as you're viewing this And then throwing that up into the air So I set that base direction and you'll see how we finish it up later While I was waiting for that to dry. I just turned to the base Starting by giving it a nice warm brown heavy Wet sort of brush like a brush over there and then giving it a traditional dry brush of dark ivory just to pick out all the details This is really a sort of quick simple base. We don't need a lot on it Um, I figured he was killing imperial fists. That's what he's killing in the the video that sort of where Horace marches Where you see his original guy in the Uh In the original trailer there and so I thought hey, let's put in a few little bit imperial fist body on here And that yellow is really really shockingly bright But the key is we're going to muddy it up. We're going to dirt it up We're going to pigment it up And so when we knock it back later often we'll want to over highlight these things Just like we did with the original black armor That way when we come back in later and mess it all up that color still shines through For things like the metallics on the base. I'm very rough, but I'm also still somewhat dry brushing I don't want to get metallic paint down in those lower areas I want to preserve the deep brown that looks like dirt trapped under these metal planks And so I'm just giving it a pretty simple dry brush of the thing Hit the bullets with some simple copper Just to get those colored and toned appropriately for the jackets from what he is shot And then comes the magic step with things like this pigment goes so far because it adds a lot of depth and realism And just life into the base So I just kind of slap around some of this red pigment and then over the top of it Do a nice thinned wash of some agrax earth shade that will not only fix the pigment in place But it will also reduce it and darken down all the colors As I apply it I do then sort of wipe away from some of the higher most or more exposed areas Like the top of the armor and the skulls with my finger your best and most trusted tool in miniature painting just to make it go To make those little bright areas stay clean and preserve a little bit of the tone Weathering the metallics are also going to be important. This is a beat up rusty crusty battle zone. So I slap on some Some vallejo dried rust there And then while it's still wet start integrating in orange rust Just because that's gonna I want it to get all mixed in with the brown I want it to feel organic and natural Where some of it is very brown orange and some of it is very speckly I want it to dry in an irregular pattern just like the actual rust would form itself And with that done Then it's just a matter of Black rimming that base Oh, what a wonderful end of this road Uh, this guy was a heck of a paint job. He has a lot going on and let me tell you what Uh hitting the black rim on this base. Hmm This was been uh, this was a rewarding one. So I know that was very fast, but there's a lot to cover I hope you enjoyed it There we go. Horus is all set all done painted ready Uh to bring down the imperium Uh, so I I have to say this was a really fun fig to paint. Um, this guy is super awesome I mean, it's just a wonderful fig. Uh, he's so mean. He's so cool looking. He's very iconic Uh, I just had a great time painting this up honestly I don't normally like painting black space marine armor, but this gave me a fun chance to experiment With some different color reflections in the armor and stuff like that Uh, and he's just a great design So kudos to the sculptors and thank you very much to gw for providing this miniature for me to paint I hope you all really enjoyed it. Uh, if you did, hey, give this video a like Subscribe for additional hobby cheating. We have new videos here every saturday As always, uh, if you want to take your next step on your hobby journey You can do so through the patreon link down below that patreon is focused on review and feedback And helping you in whatever way you need in the hobby There's also a merch store where you can support us down there Uh, but as always, I thank you so much for watching this one And we'll see you next time


It reminds me of a college party gone wrong with a mess I need to clean up while suffering a hangover. A messy desk is something I can't stand. You can have the most expensive gaming hardware from the fastest GPU and pimped out RGB lights to dual or triple monitor setups and also have a good looking and sturdy gaming desk for the rest on. But if cables and wires are on top and below your desk then you lose a lot of potential aesthetics. It is not enough that gaming hardware nowadays works well. They need to look good too. The individual craftsmanship of metal on matted plastic isn't given a chance to shine if you let spaghetti cables run amok. This is a pity because for just an additional investment of 300 pesos, you can turn an eyesore into an inspiring minimalist masterpiece. Whether your PC is brand new or an old war machine, it's probably close to your heart. But no matter how careful you are, sometimes accidents happen. Or sometimes it's not your fault. You have to go through a lot of trouble to get your unit out of the way. You don't have the controls but they can damage your devices.  It's easy to have peace of mind for your devices with ProTech Computer Insurance from Koko Gen.  The insurance covers a wide series of unfortunate events from fire and lightning to accidental damage to theft, typhoon and flood damage, broad water damage, the list goes on. And the cost is very reasonable as low as 1,000 pesos for a desktop and 1,500 for a laptop and that's for a whole year already. You can apply for ProTech Computer Insurance at any Koko Gen branch or inquire via the phone or email, details in the video description. You'll need four things for cable management. One, cable ties. Two, heavy-duty double-sided tape. You won't need this however if your cable ties come with adhesives. Three, velcro roll and four, scissors. Additionally, depending on your setup, you might need extension cords and longer display port cables. I recommend you only buy extension cords which have universal plugs so you don't need to worry about individual adapters. The display port cable which came with my monitor was too short and so I had to get a new one. I'll leave the shoppy links to these in the video description. Alternatively, you can choose to just install a cable organizer underneath your desk. However, on a personal level, I feel cable organizers which can be seen are as much as I saw as cables themselves. I want to see my plank of wood tabletop and nothing else. Additionally, I'll be attaching a heavy-duty monitor arm from my trusty 34-inch ultra-wide Samsung monitor. Monitor arms are a good way to hide cables and they free up a lot of space on the table. However, I was happy to live without one for 14 years and so I wouldn't make this a priority. I got this particular monitor arm from Amazon and had it shipped over. Step one, clear everything out. It's tempting to just begin wrapping up the cables in order to save a step but I promise you that you will waste more time doing this. Get rid of everything on your desk. Unplug all the cables from your computer until you get a blank canvas. Hey, if you like what you're watching so far, please consider liking and subscribing to Hardware Sugar where we generate regular tech content. Step two, installing the monitor arm. Monitor arms have two essential installation points. The first is installing the monitor arm without the monitor to your desk first. Okay, so I'm hoping that this will be aligned well enough. Maybe I wanted more to aside. The second is installing the monitor into the arm when the arm has already been attached to your desk. If your desk has a lip, meaning enough space for it to latch onto, then you can use a C-clamp like this one. Another option is to use a grommet but this requires that there is a pre-existing hole.  I'm going to go with the C-clamp. The top and bottom of the clamp have rubber pads to prevent damage to the desk in case you want to remove the arm in the future. Always assume, however, that there will always be some form of permanent damage. Ignore the fact that I am installing the arm on my bed when I should be doing this step while the arm is already hovering above my desk. In order to use a monitor arm, you need to know if it's Vesa compatible, which means it must have holes in the back. Go online and check your monitor model if it does and cross check to make sure that the monitor arm can handle the weight of your monitor.  Okay, so now we are just about done. We're just going to install the cable management for the arm. So far, so good. It's not exactly what I wanted but I'm considering how heavy and wide this monitor is. I'm lucky to have this stand. What I really wanted though was to have it mounted there so that the two monitors would be aligned one on top of the other. But no, it's not possible with this. Not possible. Step three, install all the cables. After the monitors are up, hook up the cables to your PC and monitors. The importance of doing this last is due to various reasons. One of which is that you might discover that there are some unused cables which you don't need in the first place. A common thing which happens when you haven't cable managed your PC for a long time. Why waste time on cables you're not actually using? All right, now the next problem is that I need an extremely long display port so that the ultrawide can reach my computer over there. So, they have to work with this for choppy. Hopefully, it will reach that place. When all the cables have been attached, begin using the velcro roll. These are extremely handy and good for the environment because you can make them as long or as short as you want and all of them can easily be recycled for second uses. Doing this now makes your next job of attaching everything to the cable ties a lot easier. Easier because instead of maneuvering 10 different cables into one tie, you just need to maneuver one massive collective cable. This also helps prevent cable sagging in between areas where you don't have a cable tie. Something useful in case you run out of cable ties or if you wish to use less adhesives. The bad thing about cable adhesives is that they wear out after a long time. I have to remove the old ones from the desk first and replace them with the heavy-duty double-sided tape. It is important that you remove the old double-sided tape from the adhesive hooks as well but I got lazy and just went straight into placing the new tape on top of the old tape. After sticking the double-sided tape to the cable tie, you want to peel off the other tape end and stick it to the back of your table without attaching any wires in order to give the adhesive enough time to adhere to the desk. Again however, I am impatient and just did away with my own procedure and just went straight into it. A testament to my urge to get my clean-looking desk ASAP. I'm making the script after the fact to help guide others and my future self on how best to get the job done in the future. It's just a little bit irritating but I'm gonna fix that and I'm not a fan of that. I can still see these wires, these two wires and these wires. Plug the power cord. However, it's not giving me enough slack so let me get the power brick up here. I place the power brick here. It seems to my Nintendo Switch dock is covering the power brick. This is what it's for. And then step four, admire your work and brainstorm. My number one goal is to not see a single cable underneath my desk. My second goal was to hide as many cables above my desk as much as I could. You can make a desk even more clean by investing in a wireless keyboard and mouse.  You won't see it when it's not in use and it is convenient to reach out for whenever you need to charge a wireless mouse. An organized and clean-looking desk may not add higher frame rates to my game but it sure as hell gets me out of bed quicker. And even when it isn't in use, I can't help but think of my desk setup as not only something useful but also as an art piece. Let us know in the comment section below what products you recommend for cable management and your recommended retailer for monitor arms. And you want to give a special shout out to our top fans. Dom H, Liam Magnae, Ian Meru, Richard Omkinko, IDX Addict, John Otcia, and Christian Espinosa. Again, thank you so much for all your support and for tuning in to our live stream. I see a lot of you. Till next time guys.


Thank you everybody for coming to my talk and thanks to the conference organizers for all their hard work and for accepting my proposal to give a talk about computer vision using Ruby and LibJIT. Okay, a footnote, two days ago I conveniently brought my glasses, so if I cannot recognize some of you at 1,000 meters distance, please don't be offended. So, most of this work was done in context of the EPSRC nanorabotics project, which is a research project in the UK, and it was about implementing a vision-based closed-loop control in a transmission electron microscope, and the work is all released on RubyForge among other websites under the name Hornets Eye. The link to the slides, for some reason, is not visible. Sorry about that. But I put the link on the Ruby website as well. So, while I did this work in context of the nanorabotics project, the intention is to write a general purpose machine vision library. So, here are a few example applications of computer vision. I don't have time to go into the details, but what I want to show today is a bit of augmented reality because many people get stuck on doing two-dimensional computer vision and because it requires a bit of a step to go into 3D, but once you have taken the step, it can do so much more. It's very interesting. By the way, the slides, I'm changing them using a camera as well. So, this presentation software is all written in Ruby. So, when my hand comes here, I can choose slides using my camera. And because I'm nervous and my hand is shaking, so I also added some functionalities, so I can just do this. If I do this, it'll just go one slide forward, like this, go one slide backward. All right. But computer vision means array operations. It's really like this. A lot of it is done using array operations. And as you can see, even the recent version of the Ruby virtual machine is still 30 times slower on this particular machine than the recent version of GCC. So, this is an example of operation creating an index array with 10 million elements. So, you may think maybe using Ruby is not such a good idea. I don't know who, if you've seen the movie, but if you've seen the movie, I know what that red light means. So, I said, okay, it doesn't matter. I'll do it in C++. I'm very good at C++. So, I wrote, for example, a plus operator for the boost multi-array class, which is a class of choice if you do n-dimensional arrays in C++.  So, they have the worst support from the language. And if you do the same thing in Ruby, you can with less than 10 lines of code, you can have a working version of an array operator already which runs on multi-dimensional arrays. So, the trick is in order to combine performance and flexibility, I use the approach similar as the NRA library that you basically implement a Ruby extension providing uniform arrays. So, arrays where each element has the same data type, for example, a duck. But I'm not using NRA. I'm implementing my own extension because, for example, NRA is written mostly in C and it's, for example, not easy to add a custom element data type. Now, I'm going to show you how this is done. It's actually not very difficult. The core of the library is very small. So, you start by defining a C extension which defines a class, a malloc class. And this malloc class, you use it to, for example, allocate 10 bytes of memory and then you can write a Ruby string to the memory or you can read back five bytes of memory and get the content as a string. And you can do pointer operations like M plus two and if you read five bytes, then it will ignore the first two bytes. Of course, you have to be aware of the problem that this is not safe against buffer overflows. So, if you read 10 bytes after increasing the pointer, it will crash. So, you have to reintroduce boundary checks at a later stage but this is part of the thing which saves a lot of time which makes a lot of performance. And so, you can use this class to define a native data type in Ruby. So, the constructor, you allocate four bytes of memory and then you have a set and a get method. I don't know, maybe some of you were in the talk earlier on. So, you just use a standard Ruby library methods, array pack and string unpack to convert a Ruby integer into a four byte string containing the native representation of that integer and back. Then you can write a native integer and on the right side of the slide is some example used where you set the, you create an integer with initial value three and then you set it to five and you can read back the value and you can make all this, you can do all this in a more generic fashion. So, you can make a more generic integer class, a parametric class if you will which has parameters, a number of bits and signed or not. And then you create a method which creates classes inheriting from that class and on the right side you can see the purpose of this. So, I say, for example, unsigned short end is an integer with 16 bits and unsigned and if you have taken care about choosing the appropriate descriptors and memory size and whatnot, then it will behave as expected and you can start using this integer. Also, what's useful to implement is some means of having several Ruby objects viewing the same memory location. In the same fashion you can implement static arrays. So, in this case you have a parametric class with parameters, number of elements, sorry, element type elements and number of elements and stride, stride you can assume to be one at this point. And selecting an element basically means taking the pointer, adding high times the size of an element to it and then creating a view which is viewing that part of the memory and the views of the element type and then you can use this to implement the standard Ruby array operators and on the right side is some example code where I say, okay, a short end is a 16 bit signed integer and then I create an array with eight elements of that type, I fill it with the default value and then I can set and retrieve elements as you would expect from an ordinary array class. And if you have implemented everything properly this will work multidimensional straight away so you can create an array of arrays. So you say in this case a 32 bit integer array, three times two array and if you implement some inspect methods to do some pretty printing it will pretend to be a multidimensional array and you can also improve your methods for selecting elements so that they will accept multiple indices or even ranges as indices in a similar fashion as the NRA library provides. In contrast to NRA library this will create a view and that memory not a copy actually. So now we have arrays and the next thing is to define operations on them and I will show you how to implement, how I implement unary and binary operations of course there are more array operations than this. So we start with scholars and I just define a method called op and the method passes its arguments to instance exec, just calls instance exec nothing more and then you can already use this to define a negate operator. The negate operator just creates a new object of this class and then it calls op with ruby value of this native element as a parameter and the operation you execute with instance exec just does set minus x, so set to the negative value and that's all and on the right side you can see an example where it works as expected you create a short integer with value three and minus s will give you a short integer with value minus three and then for arrays you also define the op method and it simply loops over all the elements and calls op recursively and if one or more arguments are arrays as well you also iterate over the elements of that array and if you do it like this you can actually implement the negation operator in exactly the same way as for the scalar and on the right side you see some example usage where I create an index array with values zero, one and two and if I negate that array I get zero, minus one, minus two so this is all nice and good but it's still very slow so how to speed up things if you look at the title of my talk you can already guess that we're going to use a widget to do this and I also use a reflection to do this so I use a reflection to compile a code to interpret code so you start with a... this is an example illustrating this where I use a smaller class which uses method missing to record what methods are being invoked on an object of this class and on the right side you can see some example use so I create two objects of this class A and B and you can see if you do operations on them it will faithfully record what's happening of course Ruby reflection has some limitations so you have to restrict yourself to a subset of Ruby when doing this so you can see there are a few operations where you won't be able to distinguish what's happening and then you integrate JIT like this so this is for scalar operations we implement a new op method and the op method will first check this self and all the arguments are there all JIT supported and if yes then we call the JIT compiler and give it all the variables, self and the arguments and the JIT compiler will convert the variables to JIT variables and call this a code block which I'm passing here and in the code block I just call the method itself again so I'll enter again at the top and because JIT variables themselves are not JIT supported I'll jump into the second case this will call the old implementation of the op method which will call instance exit in turn and to understand what happens you can for example implement a negation operator and add some print statements to it then you can see that when executing the operation you actually don't have ordinary Ruby variables but you have actually JIT variables so you have self is an integer with the value the machine register I1 is pointing at and the parameter X is another register and when you do set minus X with this variable then instead of doing computations it will generate machine code so it will generate the code for negating and writing the value to a new register and then code for writing the value of that register to the memory location I1 is pointing at and this is actually inspired by Ruby LibJIT which is another project using the LibJIT library and for arrays it gets a bit more complicated again you initialize the same way you check you get JIT support you call JIT compiler, you call yourself and then you jump into the second case and then we check are we JIT compiling? Yes, then I first get a reference to the JIT function and then I create a copy of the array pointer I compute the strides and I compute a pointer to the end of the array and then I create, this is a bit complicated I create two list of functions for the arguments to process the arguments so if the argument is an array I will add two functions one function for incrementing an array pointer and one function for extracting an element and if an argument is a scalar then I just add a function for returning that scalar and then finally comes the loop so in the loop I simply extract all the current arguments I call up recursively and then I increment all the pointers and I do this until I have reached the end of the array and here are some, here's the illustration so you see that very similar with the scalar operation it's almost the same only the register indices are higher this is because while we are generating the same machine code using the operation the library will put some looping code around that operation so you will end up with a machine code to do an array element-wise operation and here are some performance results they vary greatly depending on the machine you can see it's still sometimes six or even worse, six times slower than C++ but if nothing else helps I will just implement a small C++ code generator to CCC to beat C++ with C++ it's no problem and to the comparison I also added the NRI library so we should at least be able to reach the NRI library's performance with this concept and now I want to give an example of what one can do with the library so the question is we have an image showing a rectangular marker to determine the position of that marker in order to be able to draw a coordinate system properly into that image as shown on the right side of the slide I'm not showing you all the code I will explain some methods instead of showing the code but basically you start with opening the camera and then you read an image then you threshold that image this is an example of an element-wise array operation and then I do connected component analysis in this case we will have 93 components including the background so you set n to the maximum index of the component image plus one and then we create a histogram of the components this will give us the area of each component and then we create a binary mask to filter for the components which have a size which is within the acceptable range and then I create an index array select just the indices which I'm interested in using the mask convert it to a Ruby array and then I can loop over the indices so I'm now looping over the remaining components which are not too small and not too big and C is the loop variable and I can create a mask of the component just saying components equals C and then I can create a mask just selecting the edge pixels by taking the difference of the dilated component minus the eroded component so I get a mask with all the edge pixels and then I'm computing the gradient so I'm not showing you the source code of this method but it basically just computes the gradient vectors which direction the gradient pointing up and for convenience sake I store the gradients in complex numbers so it's complex gradients so the real and imaginary part are forming the two parts of the gradient vector and then using a mask operation I just select the creative one-dimensional array with just the gradients of the edge pixels and then you see what I'm heading up so now I try to detect dominant orientations in order to do that I compute the argument of the gradients the complex argument is in this case the gradient angle and then I quantize this into 36 bins and I create a histogram and if this is a rectangle if this is a rectangle you should end up with a histogram with four peaks so I threshold this histogram and then I look for connected components in the binary image in the resulting binary image so if this is a rectangle I should end up with four components and in the end I also create an array partitions which will tell which component each gradient is belonging to and if I have four dominant orientations then I assume I found a rectangle and then my computer is a complex ramp I'm not showing you the source code of this method but it basically is a complex array a two-dimensional array with the real and imaginary part containing the x and y coordinate of each point so we have a two-dimensional array and the first row will be 0, 1, 2, 3, 4 the next row will be 0 plus i, 1 plus i, 2 plus i the third row will be 0 plus 2i, 1 plus 2i 2 plus 2i and so on and then I do a masking operation to compute x so that x will be a one-dimensional array containing the complex coordinates if you will, of all the edge pixels and then the following two statements are just to compute the center of gravity of each line so I first create a histogram of the labels this will give me an array with the size of each line the number of pixels of each line and then I create a weighted histogram where I use the coordinates as weights and if I divide this by the number of pixels each line has I will end up with the center of gravity of each line I also will get the center of gravity of the unclassified pixels but I will ignore that later and then I need to compute the orientation of each line and in order to do this I first subtract from each edge point I subtract the coordinate of the corresponding center of the line so I will end up with vectors pointing into both directions along the line and if I would just sum them up I would end up with 0 so that's not useful but these are complex numbers so I use a trick let's say I have vectors pointing at 20 degrees and vectors pointing down the line 200 degrees if I square the complex number I will end up with twice the angle so I will have now 2 times 20 is 40 degrees and 200 times 2 is 400 modulo 360 is also 40 degrees so now I can sum them up after taking the sum I take the complex square root and I will have my orientation 20 degrees and if you do a web search for line fitting algorithms I'm sure you will end up with more source codes than this and then finally I compute the intersection of each two neighboring lines I'm not going to explain how I did this this was a bit difficult but basically then you will get the corner points of the rectangle so now you see we have gotten very far already and now we want to do 3D I want to be able to do I want to be able to find a function where I can give that function the coordinate for example say minus 2.5 centimeters minus 2.5 centimeters and it will give me the top left corner in the image or minus 2.5 centimeters and y is plus 2.5 centimeters 2.5 centimeters then it should give me the next corner so now I'm looking for a function like this so in order to do this we need to do a little bit of mass but you will be surprised in 10 minutes you will know how to do 3D vision and we start out with I guess everybody knows this the pinhole camera model the pinhole camera model just says the size of the object x1 divided by the distance of the object x3 equals the size of the image on the camera chip divided by the focal length the size of the image on the camera chip is the number of pixels times the actual size of a pixel on the chip so delta s is the pixel size on the camera chip and f is the focal length and the ratio f divided by delta s you need to know but you can for example do it using camera calibration or maybe you can get it from the specification of the camera and this of course holds for both dimensions in 3D so x1 to x3 you have an equation for the first dimension you also have an equation for the second dimension which gets projected now we take these equations these two equations and we reformulate them a little and we introduce an additional variable lambda and this is called homogeneous coordinates anybody who has done 3D graphics will be familiar with this and we just set lambda to x3 and add an additional equation that lambda has to be x3 and we require lambda to be non-zero and the reason to do this is that this will allow us to write all these projection equations using matrix vector modifications so it makes it more easy to handle and this matrix is actually the intrinsic camera matrix this will do the projection part and then it's when you've done this it's much easier to introduce additional 3D rotations and translations by just taking the point the point x1, x2, x3 the vector you just multiply with the rotation matrix and we add a translation vector and if you also use homogeneous coordinates for the 3D point and we do this by just adding an additional fourth element to the vector which is 1 if we do that we can write the rotation and translation using one single matrix multiplication and what we will do now is we will insert all those point pairs of screen coordinate and desired coordinate we have four of those pairs so we insert those so bear with me and we also need to allow for an error so now we have four of those equations so I just write it once so i is between 1 and 4 with the projection and the rotation and translation and because our object is a planar object the third coordinate is always 0 as you can see so this allows us to drop one matrix column and the zero so we will end up with the equation in the second row and then for the moment we multiply the intrinsic and extrinsic comma matrices and now we are going to look for the best matrix H which is going to minimize our overall error and now we get rid of lambda so we take the last row and we compute lambda and substitute the value and you can see it's we have the unknowns H31, H32 and so on multiplied with the error so we can isolate the error so what we do is we assume that lambda 1, lambda 2, lambda 3 and lambda 4 they are actually the depth of each point and they are very too much so we say these are weights for our error if we omit those weights we will not introduce too much of a bias so instead we optimize for the non-weighted errors and now you can see you can isolate the error easily so we have for I, 1, 2, 3 and 4 we have for each of these values we have two equations so the bottom row is basically written in one matrix equation and then we put all these equations into one big matrix and now the problem becomes the problem of finding a vector H so I've written the matrix in a stacked vector form the problem becomes the problem of finding a vector H such that the norm of m times H is minimal and in order to avoid the trivial solution you could say H0 is the best solution so in order to avoid this we impose additional constraint but the norm of H must be an unknown number mu but mu must not be 0 and here comes the big mathematical trick that this is actually the solution is actually the singular validity composition so I don't know if anybody knows the singular validity composition or anybody knows the singular validity composition so you can see you can say a singular validity composition is a more generic kind of singular sorry, a singular validity composition so a singular validity composition you can also do on non-square matrices like this and then the thing is if you have a singular vector and you say m times the singular vector if you multiply this the same vector will be the singular value so you just take the singular vector with the smallest singular value and then you have the optimal solution that's the big idea, it's not my idea I read in the paper but once you have this idea it's solved because now you know the matrix apart from a constant factor but you know that this consists of the known comma matrix and the rotation matrix and not translation vector and the vectors in our rotation matrix are always length one and the third vector which we dropped earlier because the third dimension is always zero for our points you know that the third vector must be orthogonal to those two and you know the object must be in front of us otherwise we couldn't see it so t3 is greater than zero and because otherwise we wouldn't see it either so the scalar product of the third axis and the translation vector must be negative or zero and if you compare that's a source code so after lots of thinking you end up with very little source code actually okay I haven't included the source code of a singular value decomposition I just used a singular value decomposition from the linear Ruby extension but that's all the code and at the end you have the extrinsic comma matrix and then you have enough information to draw a coordinate system like this into your image and if you want to go over this again I can recommend Zinyu Zang's paper about comma calibration and I can also recommend a chapter of Ballard and Brown's computer vision book so the slides are released on the web by the way anyway so you don't need to take notes of the URL and all this if you can find them come back to me later I put the URL on each slide but it's not visible I'm sorry about that so now I want to give you a small demo with this so basically I have a camera here and it's viewing this marker I hope it will work so here I'm watching a video how it gets properly placed onto the marker it's a bit dark but it's still working I knew you would like it except maybe for one person so you can see it really works in 3D although there's a bit of a problem because it's a bit dark in here and I also added some special effects so that it sometimes does this just for fun alright that's it pretty much so if you have any questions yes Ruby is the one we have possibly you know you could take quite a lot of this library and use the camera and the other and all the facilities that do some interesting applications I mean you just had to call my old classes so you would have I guess I don't have a Mac so I guess the camera input and maybe the display will be different it's much plugable because it only relies on memory objects to exchange data you would need to port that power and as far as I know Ruby legit runs on macOS as well next question all of the primitive operations you created on top of Libgit is that part of that Hornets-Iron? yes basically Hornets-Iron provides the array classes and it has some bindings to different IO libraries that's the other problem you need to deal with when doing computer vision so at the moment it runs under Linux and most of it runs or a lot of it runs under Windows as well and PCs so I have IO for loading images loading video files also for displaying you can hardly accelerate the video display under Linux at the moment only and the QT4 integration to display as part of a GUI and then there is well there's array classes which are making use of Libgit and then there's also means of conversion to use Ruby OpenCV or NRA and also make use of the fastest Fourier transform of the WEST library for Fourier transforms FFTW this is called the fastest Fourier transform of the WEST so the Fourier transform I'm not doing with Libgit I'm just using the FFTW library at the moment there's another thing this is a comparison with Python and OpenCV so by using closures or using lambda functions you can save a lot of code and provide a much more concise API and there's another thing I noticed I think in order to create OpenCV and other C++ libraries and performance it will also be necessary to avoid intermediate results so it's quite interesting when you could hear earlier on this morning you mentioned this problem and here's an example where I tried something where you basically you have an array but the constructor it will behave differently depending on the thread variable the purpose of all this is if you do two array operations let's say you compute A plus B plus C at the moment my library will compute A plus B and write the result to memory and then it will do this result plus C and write this to memory so you could avoid the intermediate result to save some time so I'm thinking about something like this at the moment to implement in the near future in the constructor you behave differently depending on the lazy variable of the current thread then you have a method where you can just say lazy do and then you do some computations and then you do end and then it will after the end it will mark all objects as you know you have to compute them and once I retrieve the result of one of these objects it will do the computation only at that point that's another thing I'm thinking about at the moment you also need to deal with color space conversions when you do IO many cameras they provide the luminance channel with high resolution and the color channels with lower resolution so it's split up into gray and into chroma red and chroma blue so you need to up sample chroma greens that's another thing you need to do when doing computations otherwise thank you


I'm Dr. Judson Chaney and I'm the acupuncturist here on staff at Meridian Integrative Health and Medicine. Acupuncture is a medical art and practice that's been practiced for over 2,500 years. It has a history dating all the way back to China, but it's practiced throughout the world today. At a fundamental level, acupuncture is the insertion of tiny, fine needles and very specific points in the body, those are called acupuncture points. By inserting a needle onto these points, we can cause a therapeutic effect. In over thousands of years of trial, error and observation and empirically recording what that does, we've handed down what points are good for what condition. Most people, when they want to know what acupuncture feels like, want to know does it hurt. A patient can feel a number of sensations that aren't unpleasant, but they do notice a sensation. That sensation can be warmth, tingling, pressure, dull achy sensation, and that's not a bad thing. When we're talking about who can benefit from acupuncture, my first answer is just about anyone can benefit from acupuncture. It can treat a wide variety of conditions, and certainly I would recommend people look at the World Health Organization and their recommendation and study on acupuncture and its different uses. I think that they'll find that there's a lot more things that acupuncture can treat effectively than we automatically assume. The first thing that comes out in most people's minds when it comes to acupuncture, especially in America, is the treatment of pain. And certainly that in itself is enough. Anything from arthritis to spinal, back, neck pain, it doesn't have to be chronic pain. It can be an acute pain as well. Other than that, there's a number of other conditions that acupuncture can help too. It can help the digestive system. It's useful for women's reproductive issues, whether it's fertility or dysmenorrhea. Acupuncture has been shown to be very useful for patients undergoing chemotherapy, both during chemotherapy, radiation surgery for cancer-related illnesses, and then also in the remission process as well. Acupuncture fits very well into the integrated model because it's a drug-free therapy, so there are no drug interactions involved with it. It's very safe. The risk of serious side-effect from acupuncture is very, very low. And it's gentle. As part of a treatment plan, whether it's for pain or another condition as well, it can be sometimes a very useful ally in helping to heal from that, and sometimes it can be the tipping point to help move people in the right direction.