User Guide


Lock Annotations

Lock annotations mark where you expect you will be adding explicit synchronization.


call annotate_lock_acquire(address)
call annotate_lock_release(address)
Annotate.LockAcquire([int expr]);
Annotate.LockRelease([int expr]);
(for each annotation, its argument is optional)
C# and .NET support is deprecated starting
Intel® Advisor
With C/C++
and Fortran
programs, all of the lock annotations use an address value to represent distinct locks in your final program. You can use the address value 0 to represent a global
that is the same across the entire program.
With C# programs, the argument is an
with a default value of 0 (zero).
Intel recommends that you start by using a default lock, unless you need additional locks for performance scaling.
The modeling step is aware of the standard locking routines in the Windows* OS API, as well as
Intel® oneAPI Threading Building Blocks (oneTBB)
and OpenMP*, so there is no need to annotate existing locking. Lock annotations are only required for cases where you are not already using synchronization.
The lock-acquire and lock-release annotations denote points in your program where you intend to acquire and release locks. These annotations take a single parameter, which is an address that you choose.
For example, if you decided you would have a lock used only for
, you specify the same memory address for all cases where you are protecting access to
, to represent that specific lock. The sample below uses the variable's address to represent the lock that will be associated with
You typically can use one of the following four values, using a finer granularity of synchronization when necessary:
  • The value of 0 (zero) to represent a single unspecified lock that is the same across the entire program.
  • The address of a data structure or other aggregation of data. This represents using a single lock for the collection of data.
  • The address of a member of the data collection. This represents finer-grained locking than the previous value and provides better performance.
  • A variable representing a lock as you move toward final parallel code.
This C/C++ example shows the intent for the parallel program to acquire and release a lock around the access to the global variable
in each task:
    ...     extern int glob_variable = 0;     ...     ANNOTATE_SITE_BEGIN(sitename);     for (I=0; i<N; I++) {         ANNOTATE_TASK_BEGIN(taskfunc1);         func1(I);         ANNOTATE_LOCK_ACQUIRE(&glob_variable);         glob_variable++;         ANNOTATE_LOCK_RELEASE(&glob_variable);         func2(I);         ANNOTATE_TASK_END();     }     ANNOTATE_SITE_END();     ...
This Fortran example also shows the intent to acquire and release a lock around the access to the global variable
in each task:
 ... integer :: glob_variable = 0 call annotate_site_begin("sitename") do i=1,size call annotate_task_begin("taskfunc1") call func1(i) call annotate_lock_acquire(0) glob_variable = glob_variable + 1 call annotate_lock_release(0) call func2(i) call annotate_task_end end do call annotate_site_end  ...
This C# example also shows the intent to acquire and release a lock around the access to the global variable
in each task:
 ... public int glob_variable { get{return nrOfSolutions;} set{nrOfSolutions = value;} } Annotate.SiteBegin("sitename"); for (int i = 0; i < N; i++) { Annotate.TaskBegin("taskfunc1"); func1(i); Annotate.LockAcquire(); glob_variable++; Annotate.LockRelease(); func2(i); Annotate.TaskEnd(); } Annotate.SiteEnd();   ...
The following C/C++ example is a typical use of a data item's address. It shows the use of an
address, where there is a vector of integers that are each going to have an associated lock, because the program is counting random elements of the array that will be accessed by different tasks, some of which may occasionally have the same random value. The text from adding annotations appears in
   struct Entity {        int val;    };    ...    std::vector<Entity> v;    ...    for (int I=0; i<v.size()*10000; I++) {        int random_int = random_n();        ANNOTATE_LOCK_ACQUIRE(&v[random_int]);         v[random_int].val++;      ANNOTATE_LOCK_RELEASE(&v[random_int]);    }    ...

Use Lock Annotations

Lock addresses are the basis of lock annotations, and each lock address corresponds to the intent to create a unique lock, or other synchronization mechanism, in the final program. Tasks sharing a parallel site are modeled as executing in parallel unless you describe synchronization using lock addresses, or known locking mechanisms.

Product and Performance Information


Performance varies by use, configuration and other factors. Learn more at