<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="https://alexisrozhkov.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://alexisrozhkov.github.io/" rel="alternate" type="text/html" /><updated>2019-05-10T11:41:05+00:00</updated><id>https://alexisrozhkov.github.io/feed.xml</id><title type="html">alexisrozhkov’s blog</title><entry><title type="html">TGS Salt Identification Challenge writeup</title><link href="https://alexisrozhkov.github.io/kaggle-salt-writeup/" rel="alternate" type="text/html" title="TGS Salt Identification Challenge writeup" /><published>2019-05-10T00:00:00+00:00</published><updated>2019-05-10T00:00:00+00:00</updated><id>https://alexisrozhkov.github.io/kaggle-salt-writeup</id><content type="html" xml:base="https://alexisrozhkov.github.io/kaggle-salt-writeup/">&lt;p&gt;Initially, I was going to clean up my solution, dockerize it and share a repo on GitHub, but I’ve never really gotten around to doing it, so I decided at least to share a writeup here. This competition was somewhat special for me, since it was the first one I’ve been participating in seriously, so it’s more of a novice’s impression, rather than a veteran’s breakdown of things :)&lt;/p&gt;

&lt;h3 id=&quot;first-impression&quot;&gt;First impression&lt;/h3&gt;
&lt;p&gt;The goal of the &lt;a href=&quot;https://www.kaggle.com/c/tgs-salt-identification-challenge/overview&quot;&gt;TGS Salt Identification Challenge&lt;/a&gt; was segmenting salt deposits in seismic images. The data consisted of 101x101 images along with corresponding depth values in feet, and it was accompanied by a brief explanation of the image capturing process and the physics involved.&lt;/p&gt;

&lt;p&gt;Below are some samples from training set (examples of non-empty, empty, almost empty and “fancy” masks):&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;id&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;depth&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;image&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;mask&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;8ebceef687&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;321&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;img src=&quot;/images/kaggle-salt/8ebceef687.png&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;img src=&quot;/images/kaggle-salt/8ebceef687_mask.png&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0a7e067255&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;477&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;img src=&quot;/images/kaggle-salt/0a7e067255.png&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;img src=&quot;/images/kaggle-salt/0a7e067255_mask.png&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;00a3af90ab&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;531&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;img src=&quot;/images/kaggle-salt/00a3af90ab.png&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;img src=&quot;/images/kaggle-salt/00a3af90ab_mask.png&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;8daf098aa9&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;594&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;img src=&quot;/images/kaggle-salt/8daf098aa9.png&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;img src=&quot;/images/kaggle-salt/8daf098aa9_mask.png&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;At the start of the competition, it looked like a straightforward segmentation problem, perhaps with some smart way to incorporate depth information. Participants were more focused on technical questions, like:&lt;/p&gt;

&lt;h4 id=&quot;whats-the-optimal-way-of-adapting-the-image-size-to-a-more-conventional-one&quot;&gt;What’s the optimal way of adapting the image size to a more conventional one?&lt;/h4&gt;

&lt;p&gt;UNet-like architectures, typically used for segmentation, require input dimensions to be divisible by 2 to the power of the number of downsampling layers. This is needed to ensure that “backward” path, that performs upscaling, ends up with the same set of resolutions to allow merging layer outputs from “parallel” paths.&lt;/p&gt;

&lt;p&gt;Typical answers were resizing to 128 or 256 pixels or padding to 128 pixels, but what padding mode to use then? Participants have experimented with &lt;code class=&quot;highlighter-rouge&quot;&gt;BORDER_REPLICATE&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;BORDER_REFLECT&lt;/code&gt; (in OpenCV terminology) and their different combinations (like mirror horizontally and repeat vertically), justifying this by physical nature of the data. After the competition deadline one team has shared another interesting approach, which they claim performed better in their setup: biharmonic inpainting, see &lt;a href=&quot;https://www.kaggle.com/c/tgs-salt-identification-challenge/discussion/69664#latest-410341&quot;&gt;[Argus] 14th place solution with full PyTorch pipeline&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h4 id=&quot;what-are-the-best-augmentations-here&quot;&gt;What are the best augmentations here?&lt;/h4&gt;

&lt;p&gt;Some participants argued that some “typical” ones, like random rotation, might be destroying important information (top/bottom arrangement). For me, the data was exotic enough to proceed entirely empirically :)&lt;/p&gt;

&lt;h4 id=&quot;what-loss-function-to-use&quot;&gt;What loss function to use?&lt;/h4&gt;

&lt;p&gt;There were several approaches here, namely the “Kaggle forum approach” (Lovász loss + optionally BCE loss) and the “opendatascience community approach” (dice loss + BCE loss) with different weights. It seems that “ODS approach” was motivated by the successful experience of using such combination in previous segmentation-focused competition, and “Kaggle approach” was inspired by excited reports of using &lt;a href=&quot;https://arxiv.org/abs/1705.08790&quot;&gt;Lovász loss&lt;/a&gt;, which was advertised as a more direct way of optimizing Jaccard index. There was &lt;a href=&quot;https://www.kaggle.com/c/tgs-salt-identification-challenge/discussion/63984#382913&quot;&gt;a bit of controversy around it&lt;/a&gt;, but experimentally it worked for several people, so it was still worth checking out. It was slightly trickier to use, which resulted in different variations by different participants: replacing ReLU with ELU+1 for better optimization (smoother), initially training with something common, like BCE, and then switching to Lovász, and most interesting one - &lt;a href=&quot;https://www.kaggle.com/c/tgs-salt-identification-challenge/discussion/69053#latest-416168&quot;&gt;using the symmetric version of Lovász loss&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;what-network-capacity-yields-the-best-result-on-the-provided-data&quot;&gt;What network capacity yields the best result on the provided data?&lt;/h4&gt;

&lt;p&gt;This was really interesting because during the competition several participants were reporting good results with ResNet-34 (which is considered to be small by modern standards), but after the end of the competition it turned out that many of the top entries included significantly bigger backbones, like SENet-154.&lt;/p&gt;

&lt;p&gt;Last point was quite indicative of my overall impression from the competition - there was a lot of information on the dedicated Kaggle forum, but many of the described things seemed to work only in combination with something else, and of course asking for an ablation study would be too much, given limited time to research all the possible options :) Besides, as always, the devil is in the details, and getting all the things right &lt;strong&gt;simultaneously&lt;/strong&gt; (architecture, optimizer, LR schedule, ensembling scheme) was more important than finding some “silver bullet” (relatively “tight” private leaderboard seems to confirm that)&lt;/p&gt;

&lt;h3 id=&quot;following-best-practices-isnt-enough&quot;&gt;Following best practices isn’t enough&lt;/h3&gt;

&lt;p&gt;After some time was spent on doing the “typical” research it turned out that result is still not there in terms of accuracy (compared to top entries in the leaderboard), so there was something that could be done to improve it, perhaps something competition-specific.&lt;/p&gt;

&lt;p&gt;After looking closely at the metric (mean average precision), the main hypothesis was that almost empty masks were most problematic - they have only few positive pixels, so making a few-pixel misaligned prediction might “ruin” the whole sample. Another potential issue: if a model will try to “guess” such samples without having enough information (or capacity) to do this reliably - it might end up increasing the number of false positives, which are penalized in the same way (the sample gets a 0 score).&lt;/p&gt;

&lt;p&gt;Surprisingly, the error analysis didn’t seem to confirm this - samples with different mask coverages seemed to contribute more or less equivalently to the overall error. Anyway, it seemed that treating samples with different mask coverage was beneficial, so I’ve tried different approaches to stratification. At first, I’ve made a mistake of simply binning all the samples according to “classes” of mask coverage (from empty to fully covered). Even though it seems right, in reality, it almost always mixes empty with almost empty masks, which goes directly against the purpose of such binning (unless you define the bins with the right limits explicitly). But even after fixing this, I didn’t observe improvement. When making this, I could’ve noticed the fact, that there are NO masks with 100% coverage, even though there are a lot of masks with 0% coverage. It turned out to be an important fact later on.&lt;/p&gt;

&lt;p&gt;Approximately at this time, a lot of discussions related to deep supervision started to appear on the Kaggle forum. I wasn’t familiar with this concept, but it seemed like a neat idea, so I’ve decided to give it a try. The high-level idea is to introduce an additional training signal, which is supposed to help to learn features, which will be useful for the primary task. I’ve implemented something similar to &lt;a href=&quot;https://www.kaggle.com/c/tgs-salt-identification-challenge/discussion/65933393557&quot;&gt;this&lt;/a&gt; and have been finally observing some improvement. I tried slight variations, such as performing regression of mask coverage instead of classification, or multi-class classification (empty, almost empty, vertical, etc), but haven’t been able to get better results.&lt;/p&gt;

&lt;p&gt;After implementing this and a few other tricks in decoder I felt that my experiments were stagnating, and it was time to experiment with heavier encoders. I’ve been running most of the experiments with ResNet34 encoder pretrained on ImageNet, as it was small enough to allow performing several experiments in parallel faster, than if I was doing the same thing with a bigger model. Unfortunately, I couldn’t just swap the encoder and retrain the model, many things needed to be adapted as well: decoder, batch size, LR schedule, etc. This (among other things) was preventing me from trying a wide variety of available encoders, and I ended up trying 3-4 most promising ones, and settling up on SE ResNeXt-50, which seemed to have the best “complexity”/”accuracy on ImageNet” trade-off. It resulted in a ~2x increase in training time per epoch, but the speed of convergence was comparable to my previous setup, and it eventually was outperforming it in terms of competition metric.&lt;/p&gt;

&lt;p&gt;Team Merger deadline was getting closer and even though originally I was going to participate solo until the end to make it a learning experience, I started to doubt that it is the best strategy. Solo participants at the top of the leaderboard were started to be moved by larger teams, and not merging with someone else started to look sub-optimal. Of course, even a single participant might use a diverse ensemble to get “safer” predictions, but with multiple people in the team diversity is introduced into the ensemble more naturally, besides the amount of available hardware will increase as well. Finally, it doesn’t seem to contradict learning during the competition as long as the knowledge level among the teammates is comparable. Keeping this in mind, I decided to team up with &lt;a href=&quot;https://www.kaggle.com/sawseen&quot;&gt;Ivan Sosin&lt;/a&gt;, who was close to me on the public leaderboard. Merge went really well, and since we had quite different pipelines - there was a clear synergy between our models. Below is a high-level overview of my pipeline, and Ivan’s can be found &lt;a href=&quot;https://www.kaggle.com/c/tgs-salt-identification-challenge/discussion/69165#latest-456751&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;pipeline&quot;&gt;Pipeline&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Model&lt;/strong&gt;: UNet-like architecture&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backbone&lt;/strong&gt;: SE ResNeXt-50, pretrained on ImageNet&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decoder&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Spatial and Channel Squeeze Excitation gating&lt;/li&gt;
  &lt;li&gt;Hypercolumns&lt;/li&gt;
  &lt;li&gt;Deep supervision (zero/nonzero mask)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tile size adaptation&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Pad 101 → 128&lt;/li&gt;
  &lt;li&gt;Mode - replicate (reflect was worse, reflect horizontally+replicate vertically was same, random selection as an augmentation didn’t improve as well, although more tests needed to be made)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Augmentations&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Random invert (unexpected, but visually it doesn’t change input dramatically. Also tried mean subtraction and derivative instead of raw input, but these didn’t work well)&lt;/li&gt;
  &lt;li&gt;Random cutout (some papers indicate that it’s helpful for segmentation because implicitly it causes a model to learn “inpainting” input tiles)&lt;/li&gt;
  &lt;li&gt;Random gamma-correction (makes sense, since tiles seem to be post-processed in a way that changes brightness)&lt;/li&gt;
  &lt;li&gt;Random fixed-size crop&lt;/li&gt;
  &lt;li&gt;Random horizontal flip&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Optimizer&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;SGD: momentum 0.9, weight decay 0.0001&lt;/li&gt;
  &lt;li&gt;Batch size: 16&lt;/li&gt;
  &lt;li&gt;Starting LR determined using a procedure similar to LR find from fast.ai course - 5e-2&lt;/li&gt;
  &lt;li&gt;LR schedule - cosine annealing from maximum LR, cycle length - 50 epochs, 10 cycles per experiment&lt;/li&gt;
  &lt;li&gt;Best snapshots according to metric were saved independently for each cycle, the final solution uses 2 best cycles per fold&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Loss&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Since I used deep supervision it’s a combination of 3 losses - classification loss, pure segmentation loss (using the output from an earlier layer, empty samples excluded), total loss (segmentation loss over all samples)&lt;/li&gt;
  &lt;li&gt;Classification loss - BCE&lt;/li&gt;
  &lt;li&gt;Segmentation losses - BCE + Lavasz Hinge*0.5&lt;/li&gt;
  &lt;li&gt;Segmentation loss was evaluated after cropping masks and predictions back to 101 - this seems to “fix” cases where a few-pixel corner mask was predicted on a padded mask with imperfect alignment but was cropped afterward, resulting in 0 metric per sample.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cross-validation&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;5-fold random split&lt;/li&gt;
  &lt;li&gt;Tried depth, area and “type”-based stratification, but it seemed to degrade the result&lt;/li&gt;
  &lt;li&gt;Didn’t have enough time to synchronize folds with Ivan to allow cross-validation of ensemble results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ensembling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each of us trained multiple models (5 folds x 2 best cycles), which were used to predict masks. These 10 predictions were averaged per fold, and then a threshold was applied. Ivan chose a more conservative value of 0.5 for each fold, I selected a threshold that was resulting in the best metric - even though it might lead to overfitting to the validation set.
Then ranges were aligned and predictions were averaged again; resulting predictions were thresholded and used for submission.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Post-processing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Few days before competition deadline we’ve decided to arrange predictions according to publicly shared CSV for mosaics. This was the “eureka” moment of the competition - ground truth annotation immediately became clear, and we started to look for ways to “help” the network solve the task better, taking the annotation specifics into account.&lt;/p&gt;

&lt;p&gt;Unlike some other teams, we think that ground truth annotation made sense. It seems that the way the data was acquired makes it hard to get reasonable measurements underneath the salt domes, and also it seems that salt only forms a cap and doesn’t take the whole volume under this cap (I hope that people with domain expertise will correct if that’s a wrong assumption). In this case, it wasn’t physically-sound to label block underneath salt as salt (because probably they were not). Next question is why to label the salt dome thickness this particular way? Our hypothesis is that it’s hard to make this prediction given tiles without boundary, so they were marked as “not containing salt”, and the rest of the tiles were marked properly. Probably the tile size was chosen to match the expected thickness of the salt dome, but it’s just a guess.&lt;/p&gt;

&lt;p&gt;Surprisingly, it turned out that our networks were already doing a very reasonable job in most cases and were just lacking enough context - a “bird’s eye view” should’ve been able to fix that. 2 days before the deadline we realized a way to do this - pass the tile ids along the pipeline and then apply post-processing heuristics using tile neighbor information to improve consistency of result, even though it was a bit risky (different depth values for neighboring samples probably imply that tiles were taken from different “slices” of a scan volume, so not necessarily they had aligned ground truth values).&lt;/p&gt;

&lt;p&gt;We have used both ground truth and predicted masks to construct a few rules to improve the segmentation results:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;For almost-vertical ground truth tiles (the ones with last 30 rows same, but not fully covered) - extrapolate the last row downwards till the end of the mosaic&lt;/li&gt;
  &lt;li&gt;For “caps” in ground truth tiles (the ones with fully-covered last row) - zero all tiles below&lt;/li&gt;
  &lt;li&gt;For tiles vertically “sandwiched” between predicted or ground truth masks - replace mask with the last row of tile above, if it will cause increase of mask area (ideally it should’ve been a trapezoid from the last row of tile above to the first row of tile below, but didn’t have time to do that, and potential score gain is small)&lt;/li&gt;
  &lt;li&gt;For tiles below predicted “caps” - do the same as for ground truth case&lt;/li&gt;
  &lt;li&gt;For tiles below almost-vertical predicted tiles - extract downward.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Results&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;model&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;local metric (single-fold)&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;public LB metric (5-fold ensemble)&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;private LB metric (5-fold ensemble)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Ivan’s best model&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0.859&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.866&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.881&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Mine best model&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0.865&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.872&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.887&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Team’s ensemble (TE)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;-&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.873&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.890&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;TE + postprocessing&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;-&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.881&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.892&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;It is interesting that although postprocessing heuristics improved public lb score significantly, the effect on private lb score was negligible (~0.1 increase vs 0.001). Some rules didn’t make a difference on public lb but deteriorated result on private lb significantly (last described rule caused 0.003 drop on private lb).&lt;/p&gt;

&lt;p&gt;Another observation - seems that for the majority of teams private lb score is higher than the public nonetheless. It leads us to hypothesize that public/private split wasn’t random and was cherry-picked to meet organizers’ demands in a better way. One hypothesis for why private lb score was usually higher than public - organizers excluded few-pixel masks (which were hard to predict, incurred a high penalty and probably weren’t important from a business standpoint) from the private set.&lt;/p&gt;

&lt;p&gt;We didn’t experience significant shake-up and ended up finishing with 11th place and a gold medal, which is a great result, considering that at the beginning of competition my goal was to get any medal. On the other hand, it sets the bar quite high for the next competition I’ll decide to participate in :)&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I was storing all my submissions locally, and after the competition ended I decided that they are no longer needed. But, on second thought - maybe we can make some cool and insightful visualizations from them? :)&lt;/p&gt;

&lt;p&gt;I settled on the following scheme:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;order all submits chronologically&lt;/li&gt;
  &lt;li&gt;keep only the ones that improve private lb metric&lt;/li&gt;
  &lt;li&gt;assemble them in mosaics and use as frames of an animation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It would’ve been cooler if I had raw predictions - this would’ve allowed to also see the evolution of uncertainty in particular cases, but unfortunately, all I have is binary predictions, extracted from submission CSVs.&lt;/p&gt;

&lt;p&gt;I expected to see model’s predictions be noisy at first and then converge to some reasonable solution. The result doesn’t really match this expectation but is still worth sharing I guess.&lt;/p&gt;

&lt;p&gt;You can see which types of tiles are easy for the model and are predicted properly from the very first submits, and which are tricky even in the end (until they are replaced by mosaic-specific heuristics.&lt;/p&gt;

&lt;p&gt;Few ones I found interesting in particular (blueish tiles are ground truth):&lt;/p&gt;

&lt;p&gt;Mosaic 181
&lt;img src=&quot;https://media.giphy.com/media/xBddZX1nDcnnO9wwuW/giphy.gif&quot; alt=&quot;Mosaic 181&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mosaic 40
&lt;img src=&quot;https://media.giphy.com/media/cdFv8LqaQ2sQ9UrKDr/giphy.gif&quot; alt=&quot;Mosaic 40&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mosaic 76
&lt;img src=&quot;https://media.giphy.com/media/WvikzYtAfP36GSRryK/giphy.gif&quot; alt=&quot;Mosaic 76&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mosaic 163
&lt;img src=&quot;https://media.giphy.com/media/lYhfjXaH3mLbuLw5TB/giphy.gif&quot; alt=&quot;Mosaic 163&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Judging from these animations, internal tiles annotated as empty ones aren’t difficult to classify - most are correctly predicted from the very first submission, which is scoring only 0.794 on private lb and doesn’t have any deep supervision.&lt;/p&gt;

&lt;p&gt;Instead, vertical tiles on the boundary seem to be the trickiest, and some of them aren’t handled by the model even in the last submit. It leads to the hypothesis that provided crops don’t contain enough contextual information to reliably handle salt dome boundaries, which was among the main challenges of the competition.&lt;/p&gt;</content><author><name></name></author><category term="kaggle" /><category term="deep learning" /><category term="segmentation" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexisrozhkov.github.io/images/casey-horner-1533986.jpg" /></entry><entry><title type="html">Debugging a running python script in a docker container</title><link href="https://alexisrozhkov.github.io/python-docker-debug/" rel="alternate" type="text/html" title="Debugging a running python script in a docker container" /><published>2019-03-09T00:00:00+00:00</published><updated>2019-03-09T00:00:00+00:00</updated><id>https://alexisrozhkov.github.io/python-docker-debug</id><content type="html" xml:base="https://alexisrozhkov.github.io/python-docker-debug/">&lt;p&gt;Recently I’ve experienced a seemingly random freeze in my python script, which was running inside of a docker container. It looked like a rare issue, so waiting for it to happen again was undesirable, and I wanted to extract as much information from this event as possible. Container with a hung script has been deployed to a remote server and wasn’t ready for any type of convenient debugging, which made getting any insight into what had happened seem to be a tough task. Logs didn’t help either - nothing suspicious was posted around the time of the event. The only useful bit of information I’ve been able to get was CPU utilization reported via &lt;code class=&quot;highlighter-rouge&quot;&gt;docker stats&lt;/code&gt; for a corresponding container, which was ~100%. So far it looked like a deadlock, but it wasn’t a particularly useful insight.&lt;/p&gt;

&lt;p&gt;After a bit of research, I’ve found few solutions which seemed interesting (registering a signal handler to dump thread backtraces or interrupt the program for a pdb session), but involved modifying and restarting the script, which I didn’t consider at the time. There also was an option of using gdb for getting a backtrace of a running python script, which seemed to be a step in right direction, but unfortunately didn’t provide enough information to narrow down the issue.&lt;/p&gt;

&lt;p&gt;Finally, I’ve found something that seemed like an answer - a way to get a python backtrace for a running script. It was described &lt;a href=&quot;https://wiki.python.org/moin/DebuggingWithGdb&quot;&gt;in DebuggingWithGdb section of python wiki&lt;/a&gt; and involved installing gdb and python debugging extensions. The only gotcha in my case was - the script was running inside of a container. At first, it didn’t seem like a huge deal, so I’ve attached to a container with a hung script, installed the needed tools and tried to attach to the faulty process:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ docker exec -it CONTAINER_ID /bin/bash
root@CONTAINER_ID:/usr/src/app# apt-get install gdb python3.6-dbg
...
root@CONTAINER_ID:/usr/src/app# gdb python PROCESS_ID
...
Reading symbols from python...Reading symbols from /usr/lib/debug/.build-id/72/cdaf061ffbc62f05117e8c5825ac1e700838b1.debug...done.
done.
Attaching to program: /usr/bin/python, process PROCESS_ID
Could not attach to process.  If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user.  For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.
/usr/src/app/PROCESS_ID: No such file or directory.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, I wasn’t able to attach to the process from within the container without changing something. There was another option - performing the same thing, but from the host machine. Let’s see if that works:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ sudo apt install gdb python3.6-dbg
...
alexey@laptop:~$ sudo gdb python HOST_PROCESS_ID
...
Reading symbols from python...(no debugging symbols found)...done.
Attaching to program: /usr/bin/python, process HOST_PROCESS_ID
[New LWP 9729]
[New LWP 9730]
[New LWP 9731]
[New LWP 9738]
[New LWP 9739]
[New LWP 9740]
[New LWP 9752]
[New LWP 9807]
[New LWP 9808]
[New LWP 9809]
[New LWP 9810]
Cannot access memory at address 0x24748b3024446350
Cannot access memory at address 0x24748b3024446348
Cannot access memory at address 0x24748b3024446350
Cannot access memory at address 0x24748b3024446350
Cannot access memory at address 0x24748b3024446348

warning: Target and debugger are in different PID namespaces; thread lists and other data are likely unreliable.  Connect to gdbserver inside the container.
0x00007f59d0fc4827 in ?? ()
(gdb) py-bt
Undefined command: &quot;py-bt&quot;.  Try &quot;help&quot;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Still no luck! But it might be actually due to a difference of python interpreter versions on the host system and inside the container. I didn’t actually verify this, but the fact that debugging symbols were found in the first case and not in the second seemed to agree with this hypothesis. Problem is - there’s a very particular version of python inside of the container, and I don’t really want to have it alongside with other ones on the host machine. Instead, I decided to try something else:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;run a new container on the same machine from the same image and jump directly into the bash session&lt;/li&gt;
  &lt;li&gt;when running the container, make sure it:
    &lt;ul&gt;
      &lt;li&gt;will see the processes on the host system (including the one we want to debug in another container) (&lt;code class=&quot;highlighter-rouge&quot;&gt;--pid=host&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;runs in a privileged mode (to allow fiddling with the process) (&lt;code class=&quot;highlighter-rouge&quot;&gt;--privileged&lt;/code&gt;)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ docker run -it --rm --privileged --pid=host IMAGE_NAME /bin/bash
root@DEBUGGER_CONTAINER_ID:/usr/src/app# apt install gdb python3.6-dbg
...
root@DEBUGGER_CONTAINER_ID:/usr/src/app# gdb python HOST_PROCESS_ID
...
Reading symbols from python...Reading symbols from /usr/lib/debug/.build-id/72/cdaf061ffbc62f05117e8c5825ac1e700838b1.debug...done.
done.
Attaching to program: /usr/bin/python, process HOST_PROCESS_ID
[New LWP 9729]
[New LWP 9730]
[New LWP 9731]
[New LWP 9738]
[New LWP 9739]
[New LWP 9740]
[New LWP 9752]
[New LWP 9807]
[New LWP 9808]
[New LWP 9809]
[New LWP 9810]
[Thread debugging using libthread_db enabled]
Using host libthread_db library &quot;/lib/x86_64-linux-gnu/libthread_db.so.1&quot;.

warning: Target and debugger are in different PID namespaces; thread lists and other data are likely unreliable
0x00007f59d0fc4827 in futex_abstimed_wait_cancelable (private=0, abstime=0x0, 
    expected=0, futex_word=0x7f591c000c10)
    at ../sysdeps/unix/sysv/linux/futex-internal.h:205
205    ../sysdeps/unix/sysv/linux/futex-internal.h: No such file or directory.
(gdb) py-bt
Traceback (most recent call first):
  ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Nice! Now the py-* commands are recognized, and python backtrace is shown properly. We can proceed to showing backtraces of all the threads (shorthand &lt;code class=&quot;highlighter-rouge&quot;&gt;t a a COMMAND&lt;/code&gt; comes in handy) and intensely staring at the output.&lt;/p&gt;

&lt;p&gt;In my case, it resulted in spotting fork-related lines, which was an immediate red flag, since the script was multi-threaded, and mixing these 2 is a big no-no (at least in python world). What made it interesting was the fact that the script maintainers were not aware of this call, because it was buried deep in a 3rd-party python package.&lt;/p&gt;

&lt;p&gt;At this point it was still speculation, so I’ve run the container on a different machine, and tried to reproduce the hang by increasing the number of concurrent threads and repeatedly triggering the code path that performs forking. It turned out to be reasonably easy to cause the hang, so then I proceeded to fix it - getting rid of the fork call (and a “faulty” package altogether). After performing these changes I haven’t been able to trigger the hang using the same approach as before - I guess that’s a happy ending :)&lt;/p&gt;

&lt;p&gt;PS. I found explanations in this article very helpful: &lt;a href=&quot;https://codewithoutrules.com/2018/09/04/python-multiprocessing/&quot;&gt;Stabbing yourself with a fork() in a multiprocessing.Pool full of sharks&lt;/a&gt;. Unfortunately, in my case setting the start method to &lt;code class=&quot;highlighter-rouge&quot;&gt;spawn&lt;/code&gt; didn’t help, and instead of looking deeper into why this happened, I went with a simpler approach of getting rid of the multiprocessing call at all.&lt;/p&gt;</content><author><name></name></author><category term="python" /><category term="docker" /><category term="debugging" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexisrozhkov.github.io/images/zoltan-tasi-1384972.jpg" /></entry><entry><title type="html">Installing and running Unity ml-agents on Ubuntu</title><link href="https://alexisrozhkov.github.io/unity_rl/" rel="alternate" type="text/html" title="Installing and running Unity ml-agents on Ubuntu" /><published>2019-01-26T00:00:00+00:00</published><updated>2019-01-26T00:00:00+00:00</updated><id>https://alexisrozhkov.github.io/unity_rl</id><content type="html" xml:base="https://alexisrozhkov.github.io/unity_rl/">&lt;p&gt;As soon as I’ve found out about Unity &lt;a href=&quot;https://unity3d.com/machine-learning&quot;&gt;ml-agents toolkit&lt;/a&gt; I got quite excited about it, and have been looking forward to checking it out.&lt;/p&gt;

&lt;p&gt;It’s not really about reinforcement learning algorithm implementations, but more about the opportunity to use Unity as a tool for rendering and physics simulation. One might argue that there are other alternatives, such as &lt;a href=&quot;http://www.mujoco.org/&quot;&gt;MuJoCo&lt;/a&gt;, but Unity is free for personal use (vs 500$ for MuJoCo license), plus it looks like a better choice overall (flexible rendering, scripting capabilities, big community, etc).&lt;/p&gt;

&lt;p&gt;Recently I’ve finally gotten to play with it, and I’m going to describe it in (hopefully) few following posts here. This one will be dedicated to the installation of Unity and ml-agents on Ubuntu 18.04, performing training and inference via provided tools and controlling the agents using external code.&lt;/p&gt;

&lt;h3 id=&quot;installing-unity&quot;&gt;Installing Unity&lt;/h3&gt;
&lt;p&gt;Let’s try to follow steps in &lt;a href=&quot;https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Installation.md&quot;&gt;Installation.md&lt;/a&gt;, which suggests to download Unity from &lt;a href=&quot;https://store.unity.com/download&quot;&gt;https://store.unity.com/download&lt;/a&gt; page. At the time of writing, this page says &lt;code class=&quot;highlighter-rouge&quot;&gt;Unity is available for Windows or Mac OS X&lt;/code&gt;, which is quite interesting - I was assuming that a chunk of ml-agents target audience would be using other OS :)&lt;/p&gt;

&lt;p&gt;Anyway, turns out that Linux version is still in beta (even though apparently it was released on 26 Aug 2015), and should be downloaded from the &lt;a href=&quot;https://forum.unity.com/threads/unity-on-linux-release-notes-and-known-issues.350256/&quot;&gt;Unity forum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It wasn’t obvious, and I found out about it from this &lt;a href=&quot;https://medium.com/@tijmenlv/setting-up-ml-agents-on-linux-82972c353ad7&quot;&gt;medium post&lt;/a&gt;, so credit for discovery goes to Tijmen Verhulsdonck. In fact, after finding this post, I’ve switched to following instructions from it, instead of &lt;a href=&quot;https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Installation.md&quot;&gt;Installation.md&lt;/a&gt; document. But turns out ml-agents is evolving quite fast, and some of the instructions from this guide are obsolete as well. So I will try to give as much detail as I can about the issues that I’ve had and solutions that I’ve ended up with, so it will hopefully save some time if you’re trying to do the same thing. Anyway, let’s get back to action.&lt;/p&gt;

&lt;p&gt;On the &lt;a href=&quot;https://forum.unity.com/threads/unity-on-linux-release-notes-and-known-issues.350256/&quot;&gt;Unity forum&lt;/a&gt;, go to the last page and download the installer from the link in the last post (which is to the version &lt;a href=&quot;https://beta.unity3d.com/download/6e9a27477296/UnitySetup-2018.3.0f2&quot;&gt;2018.3.0f2&lt;/a&gt; at the time of writing). It seems that installation via Unity Hub is now the preferred way, but it doesn’t seem to add any additional value, so I’ll go with a direct link to the installer.&lt;/p&gt;

&lt;p&gt;After downloading, allow executing the installer and launch it:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~/Downloads$ chmod +x UnitySetup-2018.3.0f2 
alexey@laptop:~/Downloads$ ./UnitySetup-2018.3.0f2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;During installation, accept the agreement, and choose the components you want to install (I selected only “Unity 2018.3.0f2”) and where to install them. It will download approximately a gig, and take 3.23 GB of your storage space. After download and installation are finished you might launch Unity to make sure it’s operational (but it’s not required yet).&lt;/p&gt;

&lt;h3 id=&quot;installing-ml-agents&quot;&gt;Installing ml-agents&lt;/h3&gt;
&lt;p&gt;Both guides I’ve referenced suggest installing ml-agents from source (provided as part of &lt;a href=&quot;https://github.com/Unity-Technologies/ml-agents&quot;&gt;ml-agents GitHub repo&lt;/a&gt;), but since I’m not going to mess with the code, and want to have a particular version to make this guide reproducible, I was going to simply install it via pip (&lt;code class=&quot;highlighter-rouge&quot;&gt;pip install mlagents==0.6.0&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Turns out that later we’ll need some of the assets, that are included in this repo (mostly UnitySDK dir), so it makes more sense to install from source then. I guess there’s some benefit in this after all - version of ml-agents package will be synced with versions of gym-unity package (which we might or might not use later) and assets in UnitySDK folder.&lt;/p&gt;

&lt;p&gt;It’s a good time to create a virtualenv for this project, I’m going to demonstrate that as well:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ mkvirtualenv unity-rl
Using base prefix '/usr'
New python executable in /home/alexey/.virtualenvs/unity-rl/bin/python3
Also creating executable in /home/alexey/.virtualenvs/unity-rl/bin/python
Installing setuptools, pip, wheel...
done.
virtualenvwrapper.user_scripts creating /home/alexey/.virtualenvs/unity-rl/bin/predeactivate
virtualenvwrapper.user_scripts creating /home/alexey/.virtualenvs/unity-rl/bin/postdeactivate
virtualenvwrapper.user_scripts creating /home/alexey/.virtualenvs/unity-rl/bin/preactivate
virtualenvwrapper.user_scripts creating /home/alexey/.virtualenvs/unity-rl/bin/postactivate
virtualenvwrapper.user_scripts creating /home/alexey/.virtualenvs/unity-rl/bin/get_env_details
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Some sanity checking - let’s make sure that default Python is the one we want to use (3.6 is the only one supported by ml-agents currently), and that none of the packages are installed yet:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(unity-rl) alexey@laptop:~$ python --version
Python 3.6.7
(unity-rl) alexey@laptop:~$ pip list
Package    Version
---------- -------
pip        19.0.1 
setuptools 40.6.3 
wheel      0.32.3 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s clone the repo with python packages and assets that we need, and check out the version that we’ll use (0.6.0):&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(unity-rl) alexey@laptop:~/Software$ git clone https://github.com/Unity-Technologies/ml-agents.git
...
(unity-rl) alexey@laptop:~/Software$ cd ml-agents
(unity-rl) alexey@laptop:~/Software/ml-agents$ git checkout 0.6.0
Note: checking out '0.6.0'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b &amp;lt;new-branch-name&amp;gt;

HEAD is now at cb0bfa0 Merge pull request #1494 from Unity-Technologies/release-v0.6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Time to install the ml-agents python package:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(unity-rl) alexey@laptop:~/Software/ml-agents$ cd ml-agents/
(unity-rl) alexey@laptop:~/Software/ml-agents/ml-agents$ pip install -e .
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will download and install a bunch of dependencies as well, hopefully successfully. Let’s see if we got lucky:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(unity-rl) alexey@laptop:~$ mlagents-learn --help

    
                        ▄▄▄▓▓▓▓
                   ╓▓▓▓▓▓▓█▓▓▓▓▓
              ,▄▄▄m▀▀▀'  ,▓▓▓▀▓▓▄                           ▓▓▓  ▓▓▌
            ▄▓▓▓▀'      ▄▓▓▀  ▓▓▓      ▄▄     ▄▄ ,▄▄ ▄▄▄▄   ,▄▄ ▄▓▓▌▄ ▄▄▄    ,▄▄
          ▄▓▓▓▀        ▄▓▓▀   ▐▓▓▌     ▓▓▌   ▐▓▓ ▐▓▓▓▀▀▀▓▓▌ ▓▓▓ ▀▓▓▌▀ ^▓▓▌  ╒▓▓▌
        ▄▓▓▓▓▓▄▄▄▄▄▄▄▄▓▓▓      ▓▀      ▓▓▌   ▐▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▌   ▐▓▓▄ ▓▓▌
        ▀▓▓▓▓▀▀▀▀▀▀▀▀▀▀▓▓▄     ▓▓      ▓▓▌   ▐▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▌    ▐▓▓▐▓▓
          ^█▓▓▓        ▀▓▓▄   ▐▓▓▌     ▓▓▓▓▄▓▓▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▓▄    ▓▓▓▓`
            '▀▓▓▓▄      ^▓▓▓  ▓▓▓       └▀▀▀▀ ▀▀ ^▀▀    `▀▀ `▀▀   '▀▀    ▐▓▓▌
               ▀▀▀▀▓▄▄▄   ▓▓▓▓▓▓,                                      ▓▓▓▓▀
                   `▀█▓▓▓▓▓▓▓▓▓▌
                        ¬`▀▀▀█▓

        
    Usage:
      mlagents-learn &amp;lt;trainer-config-path&amp;gt; [options]
      mlagents-learn --help

    Options:
      --env=&amp;lt;file&amp;gt;               Name of the Unity executable [default: None].
      --curriculum=&amp;lt;directory&amp;gt;   Curriculum json directory for environment [default: None].
      --keep-checkpoints=&amp;lt;n&amp;gt;     How many model checkpoints to keep [default: 5].
      --lesson=&amp;lt;n&amp;gt;               Start learning from this lesson [default: 0].
      --load                     Whether to load the model or randomly initialize [default: False].
      --run-id=&amp;lt;path&amp;gt;            The directory name for model and summary statistics [default: ppo].
      --num-runs=&amp;lt;n&amp;gt;             Number of concurrent training sessions [default: 1]. 
      --save-freq=&amp;lt;n&amp;gt;            Frequency at which to save model [default: 50000].
      --seed=&amp;lt;n&amp;gt;                 Random seed used for training [default: -1].
      --slow                     Whether to run the game at training speed [default: False].
      --train                    Whether to train model, or only run inference [default: False].
      --worker-id=&amp;lt;n&amp;gt;            Number to add to communication port (5005) [default: 0].
      --docker-target-name=&amp;lt;dt&amp;gt;  Docker volume to store training-specific files [default: None].
      --no-graphics              Whether to run the environment in no-graphics mode [default: False].
    
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Nice!&lt;/p&gt;

&lt;h3 id=&quot;running-3d-ball-environment&quot;&gt;Running 3D Ball environment&lt;/h3&gt;
&lt;p&gt;Ok, time to finally run Unity and try training/running an agent. For this purpose, we’ll refer to &lt;a href=&quot;https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Basic-Guide.md&quot;&gt;Basic-Guide.md&lt;/a&gt; from official docs. Here are my notes regarding following the steps in this guide:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up the ML-Agents Toolkit within Unity&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;step 3 - when trying to open UnitySDK directory, I get a dialog window saying “Opening Project in Non-Matching Editor Installation”. I just click “Continue”, and it seems that there are no significant consequences&lt;/li&gt;
  &lt;li&gt;steps 4 and 5 seem obsolete - &lt;code class=&quot;highlighter-rouge&quot;&gt;.NET 4.x Equivalent&lt;/code&gt; is already selected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setting up TensorFlowSharp&lt;/strong&gt;&lt;br /&gt;
For purposes of future posts, downloading and installing TensorFlowSharp plugin is not really necessary (it is used to run trained agent without external control), but I still will do it, since it helps to check if everything is working properly.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;step 2 - &lt;code class=&quot;highlighter-rouge&quot;&gt;Import it into Unity by double-clicking the downloaded file&lt;/code&gt; didn’t work for me. Instead, I had to drag and drop downloaded &lt;code class=&quot;highlighter-rouge&quot;&gt;TFSharpPlugin.unitypackage&lt;/code&gt; file from file manager into the assets folder in “Project” tab of opened Unity.&lt;br /&gt;
After that “Import Unity Package” dialog appears, you can configure what do you want to import (I’ve unticked “Android” and “iOS” under “Plugins” to save some storage, since I’m not going to deploy to mobile, but it shouldn’t make a difference if you leave them)&lt;/li&gt;
  &lt;li&gt;after opening the scene file I see following error message in the console (bottom of the screen by default) - it can be fixed by doing exactly what the error message says
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Assets/ML-Agents/Scripts/InferenceBrain/TFSharpInferenceEngine.cs(109,43): error CS0227: Unsafe code may only appear if compiling with /unsafe. Enable &quot;Allow 'unsafe' code&quot; in Player Settings to fix this error.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Steps in &lt;code class=&quot;highlighter-rouge&quot;&gt;Running a Pre-trained Model&lt;/code&gt; section looked quite confusing to me, but they do work properly. The only notice - rendering viewport in Unity looks odd after pressing the “Play” button, this can be fixed by resizing Unity window or “Game” tab.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congrats! You’ve been able to run a pre-trained TensorFlow model in Unity. Make sure that you can follow section &lt;code class=&quot;highlighter-rouge&quot;&gt;Training the environment&lt;/code&gt; as well - you should be able to enable external control of your agents to do anything useful. It worked out of the box for me so I won’t give any additional notes here.&lt;/p&gt;

&lt;h3 id=&quot;controlling-the-agents-externally&quot;&gt;Controlling the agent(s) externally&lt;/h3&gt;

&lt;p&gt;Speaking of external control - let’s try a bare-bones version of it. &lt;a href=&quot;https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Basic-Guide.md&quot;&gt;Basic-Guide.md&lt;/a&gt; has a &lt;code class=&quot;highlighter-rouge&quot;&gt;Using the Basics Jupyter Notebook&lt;/code&gt; section, which &lt;em&gt;almost&lt;/em&gt; works for me (more on that later).&lt;/p&gt;

&lt;p&gt;Since we’ve installed all the packages into a virtualenv, we need to create a “kernel” to make their imports in the notebook work. You need to do this while your virtualenv is activated:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(unity-rl) alexey@laptop:~/Software/ml-agents$ python -m ipykernel install --user --name unity-rl --display-name &quot;unity-rl&quot;
Installed kernelspec unity-rl in /home/alexey/.local/share/jupyter/kernels/unity-rl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can start jupyter:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(unity-rl) alexey@laptop:~/Software/ml-agents$ cd notebooks/
(unity-rl) alexey@laptop:~/Software/ml-agents/notebooks$ jupyter notebook
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After you open &lt;code class=&quot;highlighter-rouge&quot;&gt;getting-started.ipynb&lt;/code&gt; select &lt;code class=&quot;highlighter-rouge&quot;&gt;unity-rl&lt;/code&gt; in Kernel -&amp;gt; Change kernel - you can think of is as a jupyter equivalent of &lt;code class=&quot;highlighter-rouge&quot;&gt;workon unity-rl&lt;/code&gt;. Now you can execute the cells.&lt;/p&gt;

&lt;p&gt;Don’t forget to change &lt;code class=&quot;highlighter-rouge&quot;&gt;env_name&lt;/code&gt; from &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;../envs/3DBall&quot;&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;None&lt;/code&gt; in first code cell - that’ll run the environment, which is currently open in Unity, instead of a compiled binary, so you have to make sure Unity is running and 3DBall scene is open there. After you run the cell which creates a &lt;code class=&quot;highlighter-rouge&quot;&gt;UnityEnvironment&lt;/code&gt; you will be prompted to press “Run” in Unity - this sets up the connection between the controller script and environment. As you run other cells, you will get information about environment, run it for few episodes and close the connection.&lt;/p&gt;

&lt;p&gt;This is the way I’m going to control the agents, during both training and inferencing. But having to click “Run” manually is not acceptable (harder to automate, requires Unity Editor running, can’t run in headless mode, etc), so we have to “build” the environments. Unfortunately, this is where I get stuck - the building process completes just fine, but when trying to run produced executables I get SIGABRT in native code, which seems to be related to TensorFlow.&lt;/p&gt;

&lt;p&gt;After spending some time trying to find a workaround, I’ve realized that if I plan to always control the agents externally - I don’t really need TensorFlow, and can try to build the environment without it. And luckily it works! To do that simply remove &lt;code class=&quot;highlighter-rouge&quot;&gt;ENABLE_TENSORFLOW&lt;/code&gt; from Project Settings -&amp;gt; Player -&amp;gt; Scripting Define Symbols, rebuild the environment and - voilà! You can now replace &lt;code class=&quot;highlighter-rouge&quot;&gt;env_name&lt;/code&gt; back to &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;../envs/3DBall&quot;&lt;/code&gt; in the notebook and run it without having to click the button and keep Unity running in background.&lt;/p&gt;

&lt;p&gt;I guess that’s enough for this post, and we’ll try to do something interesting with this setup in one of the following ones.&lt;/p&gt;</content><author><name></name></author><category term="unity" /><category term="ubuntu" /><category term="reinforcement learning" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexisrozhkov.github.io/images/ekaterina-sazonova-1310803.jpg" /></entry><entry><title type="html">Some reflection and New Year’s resolution</title><link href="https://alexisrozhkov.github.io/new-year/" rel="alternate" type="text/html" title="Some reflection and New Year's resolution" /><published>2018-12-31T00:00:00+00:00</published><updated>2018-12-31T00:00:00+00:00</updated><id>https://alexisrozhkov.github.io/new-year</id><content type="html" xml:base="https://alexisrozhkov.github.io/new-year/">&lt;p&gt;It’s almost the New Year, so I feel like reflecting a bit on the past year, and thinking about the one that’ll start soon.&lt;/p&gt;

&lt;p&gt;Some say that the first step is always the hardest, but it seems that it doesn’t apply to making blog posts often (at least for me). 3 posts per year is not that much, but if we want to be on the positive side - it’s an easy bar to raise next year :)&lt;/p&gt;

&lt;p&gt;I guess that counts both as a reflection and a resolution, although quite a vague one. To make it more concrete, I’ll set a goal of &lt;strong&gt;making at least 12 posts here in 2019&lt;/strong&gt;. One might think of it as 1 post per month, but I’ll leave a small loophole, allowing myself to post several times on some months, and not posting on others. Not too ambitious, but hey, slow and steady wins the race!&lt;/p&gt;

&lt;p&gt;This should be made easier by the fact that there have been several things that I wanted to write about, but never had the proper mood to do so, including:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;moving from writing CV/ML/DL code on frontend to backend, and learning about some lower-level Python details, as well as some DevOps-related stuff&lt;/li&gt;
  &lt;li&gt;taking part in Kaggle competition seriously for the first time: TGS Salt Identification Challenge, &lt;a href=&quot;https://www.kaggle.com/c/tgs-salt-identification-challenge/discussion/69093&quot;&gt;11th place solution writeup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;doing some vision/deep-learning experiments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s a few posts already, and we’ve barely started.&lt;/p&gt;

&lt;p&gt;Since taking part in Kaggle turned out to be a great learning experience in several areas (research, implementation, working under pressure, team collaboration), I will try to &lt;strong&gt;take part in at least 2 competitions&lt;/strong&gt;, with corresponding write-ups here.&lt;/p&gt;

&lt;p&gt;I could’ve set a goal of becoming Kaggle competition master next year (which should be possible after 2 competitions), but this depends on factors beyond my control (number and skill of other participants), so I will focus on doing my best each time, and won’t get distracted by anything else.&lt;/p&gt;

&lt;p&gt;Apart from that, I feel like I should pay more attention to research in unsupervised and reinforcement learning areas. They seem to be less applicable to production right now (at least in projects that I work on), but I expect that to change as soon as research in data-rich areas will reach saturation and more attention will be drawn to approaches which lack labelled data.&lt;/p&gt;

&lt;p&gt;It’s not easy to quantify “paying more attention”, so I’ll try to &lt;strong&gt;work on toy projects involving unsupervised and reinforcement learning&lt;/strong&gt;. Still vague, but I don’t want to limit myself too much in choosing what it will look like.&lt;/p&gt;

&lt;p&gt;I guess that’s already enough to work on, and instead of throwing more stuff into this “list”, I’d rather work more on what’s already mentioned above.&lt;/p&gt;</content><author><name></name></author><category term="new year" /><category term="kaggle" /><category term="deep learning" /><summary type="html">I feel like reflecting a bit on the past year, and thinking about the one that'll start soon</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexisrozhkov.github.io/images/jenny-caywood-1249624.jpg" /></entry><entry><title type="html">Using discrete and intergated GPUs in a laptop at the same time</title><link href="https://alexisrozhkov.github.io/dualgpu/" rel="alternate" type="text/html" title="Using discrete and intergated GPUs in a laptop at the same time" /><published>2018-06-17T00:00:00+00:00</published><updated>2018-06-17T00:00:00+00:00</updated><id>https://alexisrozhkov.github.io/dualgpu</id><content type="html" xml:base="https://alexisrozhkov.github.io/dualgpu/">&lt;p&gt;It’s been a while since my last post (a lot of stuff going on at work), but as I have just upgraded to Ubuntu 18.04 and had to reinstall some stuff - I decided to share a trick I find useful.&lt;/p&gt;

&lt;p&gt;I have a laptop with 2 GPUs - discrete (GeForce GTX 950M) and integrated (Intel HD Graphics 520). Even though discrete one is not the most powerful, it’s still sometimes reasonable to train small neural networks using it. But limited memory (2 GB) quickly becomes a bottleneck, especially given that without any training 25-50% of it is already taken by gnome/xorg/etc. There is another GPU which is typically unused at all, perhaps we can use both of them at the same time? This way smaller one will be responsible for rendering UI, and the other will be completely dedicated to compute.&lt;/p&gt;

&lt;p class=&quot;notice_danger&quot;&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; I take no responsibility for the consequences of performing steps I describe below. Your computer might turn into pumpkin, your data might get lost, and you might even have to reinstall NVIDIA drivers afterwards. Try it out only if you’re feeling adventurous.&lt;/p&gt;

&lt;p&gt;Turns out it’s not a very common setup - most search results for “ubuntu dual gpu” query are about setting up 2 discrete GPUs, which is not our intention. Perhaps this use case is too narrow, but anyway I was curious enough to find a &lt;a href=&quot;https://devtalk.nvidia.com/default/topic/991849/-solved-run-cuda-on-dedicated-nvidia-gpu-while-connecting-monitors-to-intel-hd-graphics-is-this-possible-/&quot;&gt;working solution&lt;/a&gt;, so I want to duplicate it here to make it easier to find, and to prevent losing it if the original page will be removed. To make this post less redundant, I will focus on my experience with it, including quirks and workarounds. This is especially important on Ubuntu 18.04, because solution described above seems to no longer work.&lt;/p&gt;

&lt;p&gt;Differences start from the location of libraries. Before, they used to be placed in &lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/local/cuda/lib64&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/lib/nvidia-xxx&lt;/code&gt; (where xxx stands for driver number) for CUDA and driver libraries, respectively. But now there doesn’t seem to be &lt;code class=&quot;highlighter-rouge&quot;&gt;nvidia-xxx&lt;/code&gt; directory created under &lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/lib&lt;/code&gt; for each version of the driver. Let’s try to find out where they are now (I omitted most of the output for brevity):&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ ldconfig -p | grep nvidia
	...
	libnvidia-opencl.so.1 (libc6,x86-64) =&amp;gt; /usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.1
	libnvidia-opencl.so.1 (libc6) =&amp;gt; /usr/lib/i386-linux-gnu/libnvidia-opencl.so.1
	libnvidia-ml.so.1 (libc6,x86-64) =&amp;gt; /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1
	libnvidia-ml.so.1 (libc6) =&amp;gt; /usr/lib/i386-linux-gnu/libnvidia-ml.so.1
	libnvidia-ml.so (libc6,x86-64) =&amp;gt; /usr/lib/x86_64-linux-gnu/libnvidia-ml.so
	libnvidia-ml.so (libc6) =&amp;gt; /usr/lib/i386-linux-gnu/libnvidia-ml.so
	...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Interesting, it seems that most of the stuff goes to &lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/lib/x86_64-linux-gnu/&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/lib/i386-linux-gnu/&lt;/code&gt; now. What about CUDA libs?&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ ldconfig -p | grep cuda
	...
	libcuda.so (libc6,x86-64) =&amp;gt; /usr/lib/x86_64-linux-gnu/libcuda.so
	libcuda.so (libc6) =&amp;gt; /usr/lib/i386-linux-gnu/libcuda.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Same here. It doesn’t seem like we need to do anything special to make libraries on those directories discoverable, but lets try to follow the steps above anyway:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;switch PRIME profile to “Power saving mode” in &lt;strong&gt;nvidia-settings&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;and add those paths to &lt;code class=&quot;highlighter-rouge&quot;&gt;LD_LIBRARY_PATH&lt;/code&gt; (via &lt;code class=&quot;highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt; for instance)&lt;/li&gt;
  &lt;li&gt;reboot&lt;/li&gt;
  &lt;li&gt;try to call &lt;strong&gt;nvidia-smi&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ nvidia-smi
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That sucks. That used to work before, what’s going on?&lt;/p&gt;

&lt;p&gt;It took me a while to find out, but it seems that now PRIME profile switching (or at least some part of it) is done via blacklisting the NVIDIA driver. That’s how &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/modprobe.d/blacklist-nvidia.conf&lt;/code&gt; looks on my machine:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
# Do not modify
# This file was generated by nvidia-prime
blacklist nvidia
blacklist nvidia-drm
blacklist nvidia-modeset
alias nvidia off
alias nvidia-drm off
alias nvidia-modeset off
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After checking out “Chapter 5. Listing of Installed Components” of &lt;a href=&quot;http://us.download.nvidia.com/XFree86/Linux-x86_64/396.24/README/index.html&quot;&gt;NVIDIA 396.24 driver documentation&lt;/a&gt;, it seems that &lt;strong&gt;nvidia-modeset&lt;/strong&gt; is responsible for &lt;code class=&quot;highlighter-rouge&quot;&gt;for programming the display engine of the GPU&lt;/code&gt; and &lt;strong&gt;nvidia-drm&lt;/strong&gt; handles &lt;a href=&quot;http://manpages.ubuntu.com/manpages/bionic/man7/drm.7.html&quot;&gt;DRM&lt;/a&gt; in some way. This means we don’t really need to turn them on, as opposed to the &lt;strong&gt;nvidia&lt;/strong&gt;, which sound pretty critical to us :)&lt;/p&gt;

&lt;p&gt;Let’s try commenting out lines that blacklist &lt;strong&gt;nvidia&lt;/strong&gt; and rebooting.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ nvidia-smi
Sun Jun 17 17:02:44 2018       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 396.24.02              Driver Version: 396.24.02                 |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 950M    Off  | 00000000:01:00.0 Off |                  N/A |
| N/A   57C    P0    N/A /  N/A |      0MiB /  2004MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wow, now we’re talking! &lt;strong&gt;nvidia-smi&lt;/strong&gt; is functioning properly and no memory is spent on rendering - that’s exactly what we need. Most importantly, training networks also works (at least with PyTorch). We’ll also achieve same results if we don’t add paths with NVIDIA and CUDA libs to &lt;code class=&quot;highlighter-rouge&quot;&gt;LD_LIBRARY_PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Following the original guide, I tried to run &lt;strong&gt;glmark2&lt;/strong&gt;, and it seems to work properly without any additional steps.&lt;/p&gt;

&lt;p&gt;A small downside is:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alexey@laptop:~$ nvidia-settings

ERROR: Unable to load info from any available system

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately I haven’t found a workaround for this yet, but on the other hand I don’t need to switch PRIME profiles often, and if I need - I can always unblacklist remaining components in &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/modprobe.d/blacklist-nvidia.conf&lt;/code&gt;, reboot and have &lt;strong&gt;nvidia-settings&lt;/strong&gt; working (if you plan to switch PRIME profile this will need 2 reboots vs one though).&lt;/p&gt;

&lt;p&gt;Another nice thing is that now after you wake laptop after suspending, you’ll no longer have a black screen - I’m quite surprised that this bug is still not fixed. But there’s no free lunch - &lt;strong&gt;nvidia-smi&lt;/strong&gt; still won’t work after suspend/wake cycle, so you’ll have to reboot anyway if you plan to use GPU.&lt;/p&gt;

&lt;p&gt;That’s it I guess. Hope it helped anyone, and here’s a TL;DR section (bottom of a post is a perfect place for it) to wrap it up:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Select NVIDIA driver in “Software &amp;amp; Updates”/”Additional Drivers”&lt;/li&gt;
  &lt;li&gt;Make sure that &lt;strong&gt;nvidia-smi&lt;/strong&gt; works and produces meaningful output. You can also check that correct GPU is detected by OS&lt;/li&gt;
  &lt;li&gt;Run “NVIDIA X Server Settings”, in “PRIME Profiles” section select “Intel (Power Saving Mode)”, reboot&lt;/li&gt;
  &lt;li&gt;Verify that now the system detects integrated GPU. &lt;strong&gt;nvidia-smi&lt;/strong&gt; shouldn’t work at this point&lt;/li&gt;
  &lt;li&gt;Make sure that under &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/modprobe.d/&lt;/code&gt; you have &lt;code class=&quot;highlighter-rouge&quot;&gt;blacklist-nvidia.conf&lt;/code&gt; or something similar&lt;/li&gt;
  &lt;li&gt;Comment out (place a &lt;code class=&quot;highlighter-rouge&quot;&gt;#&lt;/code&gt; in the beggining of the line) &lt;code class=&quot;highlighter-rouge&quot;&gt;blacklist nvidia&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;alias nvidia off&lt;/code&gt; in this file and save it&lt;/li&gt;
  &lt;li&gt;Reboot, verify that &lt;strong&gt;nvidia-smi&lt;/strong&gt; is working and produces meaningful output (Correct GPU and driver version displayed, &lt;code class=&quot;highlighter-rouge&quot;&gt;No running processes found&lt;/code&gt; shown under &lt;code class=&quot;highlighter-rouge&quot;&gt;Processes&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll be using this setup from now on, and in case I’ll discover something new I’ll update this post.&lt;/p&gt;</content><author><name></name></author><category term="nvidia" /><category term="ubuntu" /><category term="gpu" /><summary type="html">It's been a while since my last post</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexisrozhkov.github.io/images/matthew-brodeur-551933.jpg" /></entry><entry><title type="html">OpenCV and const-correctness</title><link href="https://alexisrozhkov.github.io/opencv-constcorrect/" rel="alternate" type="text/html" title="OpenCV and const-correctness" /><published>2018-01-27T00:00:00+00:00</published><updated>2018-01-27T00:00:00+00:00</updated><id>https://alexisrozhkov.github.io/opencv-constcorrect</id><content type="html" xml:base="https://alexisrozhkov.github.io/opencv-constcorrect/">&lt;p&gt;Lately I’ve started getting curious about functional programming (FP). It seems to offer benefits, which are too neat to ignore:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;simpler and more concise code,&lt;/li&gt;
  &lt;li&gt;concurrency almost “for free”,&lt;/li&gt;
  &lt;li&gt;easier unit-testing,&lt;/li&gt;
  &lt;li&gt;looser coupling between components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, employing FP can seem unusual at first and requires certain discipline, especially if you use languages not specifically tailored for FP.&lt;/p&gt;

&lt;p&gt;Purity / lack of side effects, which are usually associated with FP, are exciting concepts, but unfortunately they are often impossible or impractical to fully embrace in &lt;strong&gt;real™️&lt;/strong&gt; applications, either due to inefficiency or due to hardware/software limitations (API calls which mutate hidden state, etc). But immutability, which is intimately connected with purity, seems to be easier to apply selectively.&lt;/p&gt;

&lt;p&gt;Unfortunately, in many languages (C++ in particular) data is mutable by default, so we have to explicitly express our intent to keep particular objects unchanged throughout their lifetime. This practice is often referred to as &lt;strong&gt;const correctness&lt;/strong&gt;. Basically you just sprinkle your code with &lt;code class=&quot;highlighter-rouge&quot;&gt;const&lt;/code&gt;, and maybe even put some effort into making as much objects as possible constant (of course you should try to stay reasonable and find balance in such kind of decisions). Sounds easy, but once you start actually doing it, you end up with following benefits:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;catching occasional unintended data mutation (or even worse - logic errors due to insufficient planning)&lt;/li&gt;
  &lt;li&gt;getting rid of race conditions and need of synchronization (no need to sync state that doesn’t change)&lt;/li&gt;
  &lt;li&gt;potentially more optimized code (compiler will have more insight into what’s going to happen)&lt;/li&gt;
  &lt;li&gt;“self-documenting” function signatures (no need to explicitly mark input and output arguments)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’re some great reads in case you’re interested in efficient use of FP in C++, and lets move on:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://isocpp.org/wiki/faq/const-correctness&quot;&gt;Const Correctness, C++ FAQ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bartoszmilewski.com/2014/06/09/the-functional-revolution-in-c/&quot;&gt;The Functional Revolution in C++&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.knatten.org/2012/11/02/efficient-pure-functional-programming-in-c-using-move-semantics/&quot;&gt;Efficient Pure Functional Programming in C++ Using Move Semantics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While having few pieces of non-const correct code might be fine if properly isolated and tested, recently I’ve stumbled across something that I found really &lt;strong&gt;disturbing&lt;/strong&gt;. Turns out that refcounting mechanism behind cv::Mat allows long-ranging side effects which I personally didn’t expect (probably many people didn’t either).&lt;/p&gt;

&lt;p&gt;I can’t say that we haven’t been warned about it, here’s what &lt;a href=&quot;https://docs.opencv.org/2.4/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html#mat&quot;&gt;tutorial for an older OpenCV version&lt;/a&gt; has to say about it:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;The idea is that each Mat object has its own header, however the matrix may be shared between two instance of them by having their matrix pointers point to the same address. Moreover, the copy operators will only copy the headers and the pointer to the large matrix, not the data itself. &amp;lt;code snippet cut&amp;gt; All the above objects, in the end, point to the same single data matrix. Their headers are different, however, and making a modification using any of them will affect all the other ones as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would say that this approach is an abuse of a type system, and that it adds a great weapon to the “shoot-yourself-in-a-leg” arsenal. Simple snippet to illustrate:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;opencv2/opencv.hpp&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// developer who has access only to a header 
// might think that `outer` won't be changed.
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;corrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;outer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// you'd expect a copy here after which inner would be decoupled from outer
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// (unless you're an opencv developer).
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// in reality they become &quot;entangled&quot; due to shared content, 
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// only headers are independent.
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// safe way to write this would be to clone outer to get inner above,
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// but it incurs performance penalty which it not necessary if outer
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// is a temporary object.
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// developer who works on this function has no way of knowing 
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// whether user of this function intends to use `outer` after calling it.
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Scalar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// here we expect that cv::Mat declared as const won't be changed after loading
&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;img.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// preview before 
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imshow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;img&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// nasty function which modifies const object passed by const reference
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;corrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// preview after
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imshow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;img after corrupt(img)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;waitKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s not the first time such behaviour raises eyebrows: &lt;a href=&quot;https://stackoverflow.com/questions/13713625/is-cvmat-class-flawed-by-design&quot;&gt;Stack Overflow: Is cv::Mat class flawed by design?&lt;/a&gt;, but OpenCV dev’s responses usually involve straw man “cloning all the way would decrease performance, and that’s not what most people want” and suggest explicitly cloning when necessary, seemingly unaware of other possible solutions (providing a Mat class which is essentially immutable, but otherwise compatible with cv::Mat interface). I would argue that abusing language type system can hardly be justified by performance, which would make no sense if it compromises program correctness.&lt;/p&gt;

&lt;p&gt;But enough ranting, time to do something about it. Unfortunately, when I became fully aware of this situation with cv::Mat - too much code was influenced, so instead of coming up with something completely new my goal was fixing this behavior with minimal changes.&lt;/p&gt;

&lt;p&gt;Core concept was wrapping cv::Mat with a thin wrapper which clones the matrix &lt;strong&gt;both&lt;/strong&gt; at construction and at access. Something like that:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConstMat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// remove explicit if you're fine with automatic casting from cv::Mat 
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// to ConstMat that involves clone
&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;explicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConstMat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You might be wondering how is it better than using clone on cv::Mat directly like suggested. In fact - it’s not dramatically different, but now you cannot forget to call clone() before modification, and as a result - you can be absolutely sure that ConstMat instance will never be modified once constructed (unless someone is really motivated to do so of course). Additional benefit - when you copy ConstMat to ConstMat - default copy constructor will be used, which uses default refcounting OpenCV mechanism without clones. We can afford that, since both instances are immutable. But we ain’t done yet.&lt;/p&gt;

&lt;p&gt;Many methods or functions that operate on cv::Mat actually don’t make any changes to underlying data. This means that we can call them directly on internal data, without worrying about possible mutation and without making unneeded clones. You can implement only a subset of methods/functions that you need.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConstMat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// wrap methods that we're &quot;allowed&quot; to call
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Size&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// same for functions that don't modify cv::Mat
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// we could've used `friend` and retain the original call syntax
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// but I find this approach (return value) slightly more convenient 
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvtColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cvtColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Size&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Above I’ve made a point about temporary data, cloning which will be an unneeded overhead. Can we somehow make use of that? Move semantics to the rescue!&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConstMat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// don't clone temporaries, move instead
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;ConstMat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we don’t need to call clone() everywhere we want to make an assignment. Usage example:&lt;/p&gt;
&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;file.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cimg1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConstMat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// or more concise
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cimg2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConstMat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;file.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s a problem with this approach though, can you spot it?&lt;/p&gt;

&lt;p&gt;It’s about the refcounting. If you have multiple matrices which point to the same data, moving from one would leave moved matrix point to the same data as the first one! 
Example to demonstrate:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;file.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// several matrices share same data now
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// try to steal data from img to contruct cimg
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cimg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConstMat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// img2 &quot;sneaked&quot; into cimg's mat, and can now mess with it
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Scalar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imshow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;img2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imshow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cimg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cimg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// both images are corrupted now
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;waitKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s really not what we want. Luckily OpenCV exposes refcount in cv::Mat, so we can relatively easily fix this:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConstMat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;checkRefcountMoveOrClone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#if (CV_MAJOR_VERSION &amp;gt; 2) || ((CV_MAJOR_VERSION == 2) &amp;amp;&amp;amp; (CV_MINOR_VERSION &amp;gt; 4))
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// this works starting from 2.5
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#else
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// this worked until 2.4.9
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refcount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refcount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// move matrices with unique data and clone ones with shared
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

 &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// I prefer to let automatic casting happen here, but feel free
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// to add explicit if you want more control
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;ConstMat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checkRefcountMoveOrClone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Try running previous snippet again - now only &lt;code class=&quot;highlighter-rouge&quot;&gt;img2&lt;/code&gt; will be corrupted, and &lt;code class=&quot;highlighter-rouge&quot;&gt;cimg&lt;/code&gt; will be let intact. Nice!
Now we have a thin wrapper around cv::Mat, that prevents modification of its content, and at the same time doesn’t force you to clone it every time. You can achieve same result using cv::Mat “responsibly”, but effort to do so grows faster than the size of your codebase, so I find using this wrapper easier in the long term.&lt;/p&gt;</content><author><name></name></author><category term="OpenCV" /><category term="const-correctness" /><category term="C++11" /><summary type="html">Make cv::Mat const again!</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexisrozhkov.github.io/images/thomas-kelley-64329.jpg" /></entry><entry><title type="html">Simplest way to demonstrate quantum effects on a large scale</title><link href="https://alexisrozhkov.github.io/simple-quantum/" rel="alternate" type="text/html" title="Simplest way to demonstrate quantum effects on a large scale" /><published>2018-01-02T00:00:00+00:00</published><updated>2018-01-02T00:00:00+00:00</updated><id>https://alexisrozhkov.github.io/simple-quantum</id><content type="html" xml:base="https://alexisrozhkov.github.io/simple-quantum/">&lt;p&gt;This is more of a “hello world” post, just to make sure that github pages and jekyll are hooked up correctly, but I decided that it’d be way cooler if it had some value on its own. So I’m sharing this great video, after which I got curious enough to read a bunch of articles on quantum computing approaches and related challenges.&lt;/p&gt;

&lt;div class=&quot;youtube_container&quot;&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/zcqZHYo7ONs?rel=0&quot; frameborder=&quot;0&quot; gesture=&quot;media&quot; allow=&quot;encrypted-media&quot; allowfullscreen=&quot;&quot; class=&quot;youtube_video&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;Basically it demonstrates that effect of a polarizer cannot be explained just by attenuation of light, and as a result several other interpretations are possible. Anyway - enjoy :)&lt;/p&gt;</content><author><name></name></author><category term="quantum" /><category term="physics" /><category term="polarizer" /><summary type="html">First post to get things started</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexisrozhkov.github.io/images/rucksack-magazine-386319.jpg" /></entry></feed>