@@ -17,6 +17,55 @@ multiprocessing mode after all the compilation for all model components is
1717complete.
1818```
1919
20+ ### Top-Level Activation Options
21+
22+ Activating sharrow is done at the top level of the model settings file, typically
23+ ` settings.yaml ` , by setting the ` sharrow ` configuration setting to ` True ` :
24+
25+ ``` yaml
26+ sharrow : True
27+ ` ` `
28+
29+ The default operation for sharrow is to attempt to use the sharrow compiler for
30+ all model specifications, and to revert to the legacy pandas-based evaluation
31+ if the sharrow compiler encounters a problem. Alternatively, the ` sharrow`
32+ setting can also be set to `require` or `test`. The `require` setting
33+ will cause the model simply fail if sharrow encounters a problem, which is
34+ useful if the user is interested in ensuring maximum performance.
35+ The `test` setting will run the model in a mode where both sharrow and the
36+ legacy pandas-based evaluation are run on each model specification, and the
37+ results are compared to ensure they are substantially identical. This is
38+ useful for debugging and testing, but is not recommended for production runs
39+ as it is much slower than running only one evaluation path or the other.
40+
41+ Testing is strongly recommended during model development, as it is possible
42+ to write expressions that are valid in one evaluation mode but not the other.
43+ This can happen if model data includes `NaN` values
44+ (see [Performance Considerations](#performance-considerations)), or when
45+ using arithmatic on logical values
46+ (see [Arithmetic on Logical Values](#arithmetic-on-logical-values)).
47+
48+ # ## Caching of Precompiled Functions
49+
50+ The first time you run a model with sharrow enabled, the compiler will run
51+ and create a cache of compiled functions. This can take a long time, especially
52+ for models with many components or complex utility specifications. However,
53+ once the cache is created, subsequent runs of the model will be much faster.
54+ By default, the cached functions are stored in a subdirectory of the
55+ ` platformdirs.user_cache_dir` directory, which is located in a platform-specific
56+ location :
57+
58+ - Windows : ` %USERPROFILE%\A ppData\L ocal\A ctivitySim\A ctivitySim\C ache\. ..`
59+ - MacOS : ` ~/Library/Caches/ActivitySim/...`
60+ - Linux : ` ~/.cache/ActivitySim/...` or `~/$XDG_CACHE_HOME/ActivitySim/...`
61+
62+ The cache directory can be changed from this default location by setting the
63+ [`sharrow_cache_dir`](activitysim.core.configuration.FileSystem.sharrow_cache_dir)
64+ setting in the `settings.yaml` file. Note if you change this setting and provide
65+ a relative path, it will be interpreted as relative to the model working directory,
66+ and cached functions may not carry over to other model runs unless copied there
67+ by the user.
68+
2069# # Model Design Requirements
2170
2271Activating the `sharrow` optimizations also requires using the new
@@ -231,6 +280,35 @@ such string operations won't appear in utility specifications at all, or if they
231280do appear, they are executed only once and stored in a temporary value for re-use
232281as needed.
233282
283+ A good approach to reduce string operations in model spec files is to convert
284+ string columns to integer or categorical columns in preprocessors. This can
285+ be done using the `map` method, which can be used to convert strings to integers,
286+ for example :
287+
288+ `df['fuel_type'].map({'Gas' : 1, 'Diesel': 2, 'Hybrid': 3}).fillna(-1).astype(int)`
289+
290+ Alternatively, data columns can be converted to categorical columns with well-defined
291+ structures. Recent versions of sharrow have made significant improvements in
292+ handling of unordered categorical values, allowing for the use of possibly
293+ more intuitive categorical columns. For example, the fuel type column above
294+ could instead be redefined as a categorical column with the following code :
295+
296+ ` df['fuel_type'].astype(pd.CategoricalDtype(categories=['Gas', 'Diesel', 'Hybrid'], ordered=False))`
297+
298+ It is important that the categories are defined with the same set of values
299+ in the same order, as any deviation will from this will void the compiler cache
300+ and cause the model specification to be recompiled. This means that using
301+ ` x.astype('category')` is not recommended, as the categories will be inferred
302+ from the data and may not be consistent across multiple calls to the model
303+ specification evaluator.
304+
305+ ` ` ` {note}
306+ Beginning with ActivitySim version 1.3, string-valued
307+ columns created in preprocessors are converted to categorical columns automatically,
308+ which means that ignoring encoding for string-valued outputs is equivalent to
309+ using the ` astype('category')` method, and is not recommended.
310+ ```
311+
234312For models with utility expressions that include a lot of string comparisons,
235313(e.g. because they are built for the legacy ` pandas.eval ` interpreter and have not
236314been updated) sharrow can be disabled by setting
@@ -410,7 +488,7 @@ taz_skims:
410488` ` `
411489
412490If groups of similarly named variables should have the same encoding applied,
413- they can be identifed by regular expressions ("regex") instead of explicitly
491+ they can be identified by regular expressions ("regex") instead of explicitly
414492giving each name. For example :
415493
416494` ` ` yaml
@@ -485,3 +563,76 @@ taz_skims:
485563
486564For more details on all the settings available for digital encoding, see
487565[DigitalEncoding](activitysim.core.configuration.network.DigitalEncoding).
566+
567+ # # Troubleshooting
568+
569+ If you encounter errors when running the model with sharrow enabled, it is
570+ important to address them before using the model for analysis. This is
571+ especially important when errors are found running in "test" mode (activated
572+ by `sharrow : test` in the top level settings.yaml). Errors may
573+ indicate that either sharrow or the legacy evaluator is not correctly processing
574+ the mathematical expressions in the utility specifications.
575+
576+ # ## "utility not aligned" Error
577+
578+ One common error that can occur when running the model with sharrow in "test"
579+ mode is the "utility not aligned" error. This error occurs when a sharrow
580+ compiled utility calculation does not sufficiently match the legacy utility
581+ calculation. We say "sufficiently" here because the two calculations may have
582+ slight differences due to numerical precision optimizations applied by sharrow.
583+ These optimizations can result in minor differences in the final utility values,
584+ which are typically inconsequential for model results. However, if the differences
585+ are too large, the "utility not aligned" error will be raised. This error does
586+ not indicate whether the incorrect result is from the sharrow or legacy calculation
587+ (or both), and it is up to the user to determine how to align the calculations
588+ so they are reflective of the model developer's intent.
589+
590+ To troubleshoot the "utility not aligned" error, the user can use a Python debugger
591+ to compare the utility values calculated by sharrow and the legacy evaluator.
592+ ActivitySim also includes error handler code that will attempt to find the
593+ problematic utility expression and print it to the console or log file, under the
594+ heading "possible problematic expressions". This can be helpful in quickly narrowing
595+ down which lines of a specification file are causing the error.
596+
597+ Common causes of the "utility not aligned" error include :
598+
599+ - model data includes `NaN` values but the component settings do not
600+ disable `fastmath` (see [Performance Considerations](#performance-considerations))
601+ - incorrect use of arithmatic on logical values (see
602+ [Arithmetic on Logical Values](#arithmetic-on-logical-values))
603+
604+ # ## Insufficient system resources
605+
606+ For large models run on large servers, it is possible to overwhelm the system
607+ with too many processes and threads, which can result in the following error :
608+
609+ ` ` `
610+ OSError: Insufficient system resources exist to complete the requested service
611+ ` ` `
612+
613+ This error can be resolved by reducing the number of processes and/or threads per
614+ process. See [Multiprocessing](../users-guide/performance/multiprocessing.md) and
615+ [Multithreading](../users-guide/performance/multithreading.md) in the User's Guide
616+ for more information on how to adjust these settings.
617+
618+ # ## Permission Error
619+
620+ If running a model using multiprocessing with sharrow enabled, it is necessary
621+ to have pre-compiled all the utility specifications to prevent the multiple
622+ processes from competing to write to the same cache location on disk. Failure
623+ to do this can result in a permission error, as some processes may be unable to
624+ write to the cache location.
625+
626+ ```
627+ PermissionError: The process cannot access the file because it is being used by another process
628+ ```
629+
630+ To resolve this error, run the model with sharrow enabled in single-process mode
631+ to pre-compile all the utility specifications. If that does not resolve the error,
632+ it is possible that some compiling is being triggered in multiprocess steps that
633+ is not being handled in the single process mode. This is likely due to the presence
634+ of string or categorical columns created in a preprocessor that are not being
635+ stored in a stable data format. To resolve this error, ensure that all expressions
636+ in pre-processors are written in a manner that results in stable data types (e.g.
637+ integers, floats, or categorical columns with a fixed set of categories). See
638+ see [Performance Considerations](#performance-considerations)) for examples.
0 commit comments