<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<style type="text/css" style="display:none;"><!-- P {margin-top:0;margin-bottom:0;} --></style>
<div id="divtagdefaultwrapper" style="font-size:12pt;color:#000000;background-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;">
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">"1) More even space usage across OSTs (mostly relevant for *really* big files, ..."</span><br>
</p>
<p><br>
</p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">When OSTs are almost full and user writes large file it can overfill the OSTs. Having file OSTs striped over several
 OSTs somewhat mitigates this issue.</span></p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;"><br>
</span></p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">2) bandwidth ...</span></p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">It is better to benchmark the application.</span></p>
<p><br>
</p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">There is third aspect (</span><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">"write
 multiplication effect") </span><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">of wide striping we faced few times when retiring/emptying OSTs.</span></p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">Say, I need to empty out 10 TB out of retiring or failed OST, and files have striping N=16. </span><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">I
 got the list of files on this OSTs to migrate. The total size I need to rebalance is N times bigger, 160 TB in this example. </span></p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;"><br>
</span></p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">This can be addressed by (a) copying out selected stripes of the files and leaving other stripes sparse in new file,
 then (b) switching layout of  selected stripes. Both (a) and (b) not implemented.</span></p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;"><br>
</span></p>
<p><span style="color: rgb(33, 33, 33); font-family: wf_segoe-ui_normal, 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 15px;">Best regards, Alex.</span></p>
</div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> lustre-discuss <lustre-discuss-bounces@lists.lustre.org> on behalf of Patrick Farrell <paf@cray.com><br>
<b>Sent:</b> Wednesday, May 18, 2016 2:22:11 PM<br>
<b>To:</b> lustre-discuss@lists.lustre.org<br>
<b>Subject:</b> Re: [lustre-discuss] stripe count recommendation, and proposal for auto-stripe tool</font>
<div> </div>
</div>
<div>Nathan,<br>
<br>
This *is* excellent fodder for discussion.<br>
<br>
A few thoughts from a developer perspective.  When you stripe a file to multiple OSTs, you're spreading the data out across multiple targets, which (to my mind) has two purposes:<br>
1) More even space usage across OSTs (mostly relevant for *really* big files, since in general, singly striped files are distributed across OSTs anyway)<br>
2) Better bandwidth/parallelism for accesses to the file.<br>
<br>
The first one lends itself well to a file size based heuristic, but I'm not sure the second one does.  That's more about access patterns.  I'm not sure that you see much bandwidth benefit from striping with a single client, at least as long as an individual
 OST is fast relative to a client (increasingly common, I think, with flash and larger RAID arrays).  So then, whatever the file size, if it's accessed from one client, it should probably be single striped.<br>
<br>
Also, for shared files, client count relative to stripe count has a huge impact on write performance.  Assuming strided I/O patterns, anything more than 1 client per stripe/OST is actually worse than 1 client.  (See my lock ahead presentation at LUG'15 for
 more on this.)  Read performance doesn't share this weirdness, though.<br>
<br>
All that's to say that for case 2 above, at least for writing, it's access pattern/access parallelism, not size, which matters.  I'm sure there's some correlation between file size and how parallel the access pattern is, but it might be very loose, and at least
 write performance doesn't scale linearly with stripe size.  Instead, the behavior is complex.<br>
<br>
So in order to pick an ideal striping with case 2 in mind, you really need to understand the application access pattern.  I can't see another way to do that goal justice.  (The Lustre ADIO in the MPI I/O library does this, partly by controlling the I/O pattern
 through I/O aggregation for collective I/Os.)<br>
<br>
So I think your tool can definitely help with case 1, not so sure about case 2.<br>
<br>
- Patrick<br>
<br>
<div class="moz-cite-prefix">On 05/18/2016 12:22 PM, Nathan Dauchy - NOAA Affiliate wrote:<br>
</div>
<blockquote cite="mid:CAO9q2DnAGV8ayRRBLw39WJfwury0-OtCVqb0XJLgvk0Gcg=M3A@mail.gmail.com" type="cite">
<div dir="ltr">
<div class="gmail_quote">
<div dir="ltr">
<div>
<div>Greetings All,</div>
<div><br>
</div>
<div>I'm looking for your experience and perhaps some lively discussion regarding "best practices" for choosing a file stripe count.  The Lustre manual has good tips on "Choosing a Stripe Size", and in practice the default 1M rarely causes problems on our systems.
 Stripe Count on the other hand is far more difficult to chose a single value that is efficient for a general purpose and multi-use site-wide file system.</div>
<div><br>
</div>
<div>Since there is the "increased overhead" of striping, and weather applications do unfortunately write MANY tiny files, we usually keep the filesystem default stripe count at 1.  Unfortunately, there are several users who then write very large and shared-access
 files with that default.  I would like to be able to tell them to restripe... but without digging into the specific application and access pattern it is hard to know what count to recommend.  Plus there is the "stripe these but not those" confusion... it is
 common for users to have a few very large data files and many small log or output image files in the SAME directory.</div>
<div><br>
</div>
<div>What do you all recommend as a reasonable rule of thumb that works for "most" user's needs, where stripe count can be determined based only on static data attributes (such as file size)?  I have heard a "stripe per GB" idea, but some have said that escalates
 to too many stripes too fast.  ORNL has a knowledge base article that says use a stripe count of "File size / 100 GB", but does that make sense for smaller, non-DOE sites?  Would stripe count = Log2(size_in_GB)+1 be more generally reasonable?  For a 1 TB file,
 that actually works out to be similar to ORNL, only gets there more gradually:</div>
<div>
<div>    <a moz-do-not-send="true" href="https://www.olcf.ornl.gov/kb_articles/lustre-basics/#Stripe_Count" target="_blank">
https://www.olcf.ornl.gov/kb_articles/lustre-basics/#Stripe_Count</a><br>
</div>
</div>
<div><br>
</div>
<div>Ideally, I would like to have a tool to give the users and say "go restripe your directory with this command" and it will do the right thing in 90% of cases.  See the rough patch to lfs_migrate (included below) which should help explain what I'm thinking. 
 Probably there are more efficient ways of doing things, but I have tested it lightly and it works as a proof-of-concept.</div>
<div><br>
</div>
<div>With a good programmatic rule of thumb, we (as a Lustre community!) can eventually work with application developers to embed the stripe count selection into their code and get things at least closer to right up front.  Even if trial and error is involved
 to find the optimal setting, at least the rule of thumb can be a _starting_point_ for the users, and they can tweak it from there based on application, model, scale, dataset, etc.</div>
<div><br>
</div>
<div>Thinking farther down the road, with progressive file layout, what algorithm will be used as the default?  If Lustre gets to the point where it can rebalance OST capacity behind the scenes, could it also make some intelligent choice about restriping very
 large files to spread out load and better balance capacity?  (Would that mean we need a bit set on the file to flag whether the stripe info was set specifically by the user or automatically by Lustre tools or it was just using the system default?)  Can the
 filesystem track concurrent access to a file, and perhaps migrate the file and adjust stripe count based on number of active clients?</div>
<div><br>
</div>
<div>I appreciate any and all suggestions, clarifying questions, heckles, etc.  I know this is a lot of questions, and I certainly don't expect definitive answers on all of them, but I hope it is at least food for thought and discussion! :)</div>
<div><br>
</div>
<div>Thanks,</div>
<div>Nathan</div>
<div><br>
</div>
</div>
<div><br>
</div>
<div>
<div>--- lfs_migrate-2.7.1<span style="white-space:pre-wrap"> </span>2016-05-13 12:46:06.828032000 +0000</div>
<div>+++ lfs_migrate.auto-count<span style="white-space:pre-wrap"> </span>2016-05-17 21:37:19.036589000 +0000</div>
<div>@@ -21,8 +21,10 @@</div>
<div> </div>
<div> usage() {</div>
<div>     cat -- <<USAGE 1>&2</div>
<div>-usage: lfs_migrate [-c <stripe_count>] [-h] [-l] [-n] [-q] [-R] [-s] [-y] [-0]</div>
<div>+usage: lfs_migrate [-A] [-c <stripe_count>] [-h] [-l] [-n] [-q] [-R] [-s] [-v] [-y] [-0]</div>
<div>                    [file|dir ...]</div>
<div>+    -A restripe file using an automatically selected stripe count</div>
<div>+       currently Stripe Count = Log2(size_in_GB)</div>
<div>     -c <stripe_count></div>
<div>        restripe file using the specified stripe count</div>
<div>     -h show this usage message</div>
<div>@@ -31,11 +33,11 @@</div>
<div>     -q run quietly (don't print filenames or status)</div>
<div>     -R restripe file using default directory striping</div>
<div>     -s skip file data comparison after migrate</div>
<div>+    -v be verbose and print information about each file</div>
<div>     -y answer 'y' to usage question</div>
<div>     -0 input file names on stdin are separated by a null character</div>
<div> </div>
<div>-The -c <stripe_count> option may not be specified at the same time as</div>
<div>-the -R option.</div>
<div>+Only one of the '-A', '-c', or '-R' options may be specified at a time.</div>
<div> </div>
<div> If a directory is an argument, all files in the directory are migrated.</div>
<div> If no file/directory is given, the file list is read from standard input.</div>
<div>@@ -48,15 +50,19 @@</div>
<div> </div>
<div> OPT_CHECK=y</div>
<div> OPT_STRIPE_COUNT=""</div>
<div>+OPT_AUTOSTRIPE=""</div>
<div>+OPT_VERBOSE=""</div>
<div> </div>
<div>-while getopts "c:hlnqRsy0" opt $*; do</div>
<div>+while getopts "Ac:hlnqRsvy0" opt $*; do</div>
<div>     case $opt in</div>
<div>+<span style="white-space:pre-wrap"> </span>A) OPT_AUTOSTRIPE=y;;</div>
<div> <span style="white-space:pre-wrap"> </span>c) OPT_STRIPE_COUNT=$OPTARG;;</div>
<div> <span style="white-space:pre-wrap"> </span>l) OPT_NLINK=y;;</div>
<div> <span style="white-space:pre-wrap"> </span>n) OPT_DRYRUN=n; OPT_YES=y;;</div>
<div> <span style="white-space:pre-wrap"> </span>q) ECHO=:;;</div>
<div> <span style="white-space:pre-wrap"> </span>R) OPT_RESTRIPE=y;;</div>
<div> <span style="white-space:pre-wrap"> </span>s) OPT_CHECK="";;</div>
<div>+<span style="white-space:pre-wrap"> </span>v) OPT_VERBOSE=y;;</div>
<div> <span style="white-space:pre-wrap"> </span>y) OPT_YES=y;;</div>
<div> <span style="white-space:pre-wrap"> </span>0) OPT_NULL=y;;</div>
<div> <span style="white-space:pre-wrap"> </span>h|\?) usage;;</div>
<div>@@ -69,6 +75,16 @@</div>
<div> <span style="white-space:pre-wrap"> </span>echo "$(basename $0) error: The -c <stripe_count> option may not" 1>&2</div>
<div> <span style="white-space:pre-wrap"> </span>echo "be specified at the same time as the -R option." 1>&2</div>
<div> <span style="white-space:pre-wrap"> </span>exit 1</div>
<div>+elif [ "$OPT_STRIPE_COUNT" -a "$OPT_AUTOSTRIPE" ]; then</div>
<div>+<span style="white-space:pre-wrap"> </span>echo ""</div>
<div>+<span style="white-space:pre-wrap"> </span>echo "$(basename $0) error: The -c <stripe_count> option may not" 1>&2</div>
<div>+<span style="white-space:pre-wrap"> </span>echo "be specified at the same time as the -A option." 1>&2</div>
<div>+<span style="white-space:pre-wrap"> </span>exit 1</div>
<div>+elif [ "$OPT_AUTOSTRIPE" -a "$OPT_RESTRIPE" ]; then</div>
<div>+<span style="white-space:pre-wrap"> </span>echo ""</div>
<div>+<span style="white-space:pre-wrap"> </span>echo "$(basename $0) error: The -A option may not be specified at" 1>&2</div>
<div>+<span style="white-space:pre-wrap"> </span>echo "the same time as the -R option." 1>&2</div>
<div>+<span style="white-space:pre-wrap"> </span>exit 1</div>
<div> fi</div>
<div> </div>
<div> if [ -z "$OPT_YES" ]; then</div>
<div>@@ -107,7 +123,7 @@</div>
<div> <span style="white-space:pre-wrap"> </span>$ECHO -n "$OLDNAME: "</div>
<div> </div>
<div> <span style="white-space:pre-wrap"> </span># avoid duplicate stat if possible</div>
<div>-<span style="white-space:pre-wrap"> </span>TYPE_LINK=($(LANG=C stat -c "%h %F" "$OLDNAME" || true))</div>
<div>+<span style="white-space:pre-wrap"> </span>TYPE_LINK=($(LANG=C stat -c "%h %F %s" "$OLDNAME" || true))</div>
<div> </div>
<div> <span style="white-space:pre-wrap"> </span># skip non-regular files, since they don't have any objects</div>
<div> <span style="white-space:pre-wrap"> </span># and there is no point in trying to migrate them.</div>
<div>@@ -127,11 +143,6 @@</div>
<div> <span style="white-space:pre-wrap"> </span>continue</div>
<div> <span style="white-space:pre-wrap"> </span>fi</div>
<div> </div>
<div>-<span style="white-space:pre-wrap"> </span>if [ "$OPT_DRYRUN" ]; then</div>
<div>-<span style="white-space:pre-wrap"> </span>echo -e "dry run, skipped"</div>
<div>-<span style="white-space:pre-wrap"> </span>continue</div>
<div>-<span style="white-space:pre-wrap"> </span>fi</div>
<div>-</div>
<div> <span style="white-space:pre-wrap"> </span>if [ "$OPT_RESTRIPE" ]; then</div>
<div> <span style="white-space:pre-wrap"> </span>UNLINK=""</div>
<div> <span style="white-space:pre-wrap"> </span>else</div>
<div>@@ -140,16 +151,43 @@</div>
<div> <span style="white-space:pre-wrap"> </span># then we don't need to do this getstripe/mktemp stuff.</div>
<div> <span style="white-space:pre-wrap"> </span>UNLINK="-u"</div>
<div> </div>
<div>-<span style="white-space:pre-wrap"> </span>[ "$OPT_STRIPE_COUNT" ] && COUNT=$OPT_STRIPE_COUNT ||</div>
<div>-<span style="white-space:pre-wrap"> </span>COUNT=$($LFS getstripe -c "$OLDNAME" \</div>
<div>-<span style="white-space:pre-wrap"> </span>2> /dev/null)</div>
<div> <span style="white-space:pre-wrap"> </span>SIZE=$($LFS getstripe $LFS_SIZE_OPT "$OLDNAME" \</div>
<div> <span style="white-space:pre-wrap"> </span>      2> /dev/null)</div>
<div>+<span style="white-space:pre-wrap"> </span>if [ "$OPT_AUTOSTRIPE" ]; then</div>
<div>+<span style="white-space:pre-wrap"> </span>FILE_SIZE=${TYPE_LINK[3]}<br>
</div>
<div>+<span style="white-space:pre-wrap"> </span># (math in bash is dumb, so depend on common tools, and there are options for that...)</div>
<div>+<span style="white-space:pre-wrap"> </span># Stripe Count = Log2(size_in_GB)</div>
<div>+<span style="white-space:pre-wrap"> </span>#COUNT=$(echo $FILE_SIZE | awk '{printf "%.0f\n",log($1/1024/1024/1024)/log(2)}')</div>
<div>+<span style="white-space:pre-wrap"> </span>#COUNT=$(printf "%.0f\n" $(echo "l($FILE_SIZE/1024/1024/1024) / l(2)" | bc -l))</div>
<div>+<span style="white-space:pre-wrap"> </span>COUNT=$(echo "l($FILE_SIZE/1024/1024/1024) / l(2) + 1" | bc -l | cut -d . -f 1)</div>
<div>+<span style="white-space:pre-wrap"> </span># Stripe Count = size_in_GB</div>
<div>+<span style="white-space:pre-wrap"> </span>#COUNT=$(echo "scale=0; $FILE_SIZE/1024/1024/1024" | bc -l | cut -d . -f 1)</div>
<div>+<span style="white-space:pre-wrap"> </span>[ "$COUNT" -lt 1 ] && COUNT=1</div>
<div>+<span style="white-space:pre-wrap"> </span># (does it make sense to skip the file if old</div>
<div>+<span style="white-space:pre-wrap"> </span># and new stripe count are identical?)</div>
<div>+<span style="white-space:pre-wrap"> </span>else</div>
<div>+<span style="white-space:pre-wrap"> </span>[ "$OPT_STRIPE_COUNT" ] && COUNT=$OPT_STRIPE_COUNT ||</div>
<div>+<span style="white-space:pre-wrap"> </span>COUNT=$($LFS getstripe -c "$OLDNAME" \</div>
<div>+<span style="white-space:pre-wrap"> </span>2> /dev/null)</div>
<div>+<span style="white-space:pre-wrap"> </span>fi</div>
<div> </div>
<div> <span style="white-space:pre-wrap"> </span>[ -z "$COUNT" -o -z "$SIZE" ] && UNLINK=""</div>
<div>-<span style="white-space:pre-wrap"> </span>SIZE=${LFS_SIZE_OPT}${SIZE}</div>
<div> <span style="white-space:pre-wrap"> </span>fi</div>
<div> </div>
<div>+<span style="white-space:pre-wrap"> </span>if [ "$OPT_DRYRUN" ]; then</div>
<div>+<span style="white-space:pre-wrap"> </span>if [ "$OPT_VERBOSE" ]; then</div>
<div>+<span style="white-space:pre-wrap"> </span>echo -e "dry run, would use count=${COUNT} size=${SIZE}"</div>
<div>+<span style="white-space:pre-wrap"> </span>else</div>
<div>+<span style="white-space:pre-wrap"> </span>echo -e "dry run, skipped"</div>
<div>+<span style="white-space:pre-wrap"> </span>fi</div>
<div>+<span style="white-space:pre-wrap"> </span>continue</div>
<div>+<span style="white-space:pre-wrap"> </span>fi</div>
<div>+<span style="white-space:pre-wrap"> </span>if [ "$OPT_VERBOSE" ]; then</div>
<div>+<span style="white-space:pre-wrap"> </span>echo -n "(count=${COUNT} size=${SIZE}) "</div>
<div>+<span style="white-space:pre-wrap"> </span>fi</div>
<div>+</div>
<div>+<span style="white-space:pre-wrap"> </span>[ "$SIZE" ] && SIZE=${LFS_SIZE_OPT}${SIZE}</div>
<div>+</div>
<div> <span style="white-space:pre-wrap"> </span># first try to migrate inside lustre</div>
<div> <span style="white-space:pre-wrap"> </span># if failed go back to old rsync mode</div>
<div> <span style="white-space:pre-wrap"> </span>if [[ $RSYNC_MODE == false ]]; then</div>
</div>
<div><br>
</div>
</div>
</div>
</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset> <br>
<pre wrap="">_______________________________________________
lustre-discuss mailing list
<a class="moz-txt-link-abbreviated" href="mailto:lustre-discuss@lists.lustre.org">lustre-discuss@lists.lustre.org</a>
<a class="moz-txt-link-freetext" href="http://lists.lustre.org/listinfo.cgi/lustre-discuss-lustre.org">http://lists.lustre.org/listinfo.cgi/lustre-discuss-lustre.org</a>
</pre>
</blockquote>
<br>
</div>
</body>
</html>