• Skip to primary navigation
  • Skip to main content
  • Skip to footer

Codee

Automated code inspection for performance

  • Product
  • Use Cases
  • Resources
    • Catalog of best practice rules
    • Webinars
    • Blog
    • Releases
  • Company
    • About us
    • News
    • Careers
  • Request a demo

31/05/2021 Por Codee Team Leave a Comment

How to get started with Codee: Canny example

Last updated on September 15, 2022

In this blog post, we show how to get started with Codee using the Canny edge detection image processing algorithm. You will see how it supports the performance optimization roadmap by providing human-readable actionable items to enable the optimization of sequential code as well as the exploitation of the parallelism available in the target hardware platform.

A structured report displays the actionable items for the optimization of the sequential code, including faster scalar processing, simpler control flow and more efficient usage of the memory of the computer. The report also displays items for the optimization of parallel processing through vectorization, multithreading and offloading. You will see how to dig deeper into the details of each human-readable actionable item in order to understand where the performance issue is, what it is about and how to fix it.

Code structure

You can find the Canny code in our performance-demos public repository. It consists of a single canny.c file and a Makefile to build and run the code for a test image. Please note that the image is located in the parent folder in the repository and you need to ensure that it is located there for the make run target to work.

The algorithm itself essentially highlights the edges of a given image, which is illustrated in the following image:

How to build and run

As described before, there is a Makefile that you can use to build and run. By simply invoking make all the targets will be invoked resulting in cleaning any previous builds, building the binary and invoking it for the test image:

$ make
rm -fr canny testvecs
cc canny.c -fopenmp -O3 -lm -o canny
unzip ../15360_8640.zip
Archive:  ../15360_8640.zip
   creating: testvecs/
   creating: testvecs/input/
  inflating: testvecs/input/15360_8640.pgm  
./canny testvecs/input/15360_8640.pgm 0.5 0.7 0.9
Total time: 11.688

Using Codee

1. Ensure you have the latest version

Please run the following to ensure that you have the latest version of Codee matching the steps and outputs described here:

Get the latest version of Codee Contact us ›

$ pwreport --version
Codee: 1.5.1 (rev 31fd1db053e6)

C/C++/Fortran source code syntactic parsing based on:
- Clang 13.0
- Flang 'fir-dev' branch (rev 0b95852b0d00)
- LLVM 13.0

Supported scientific libraries:
- libmath C11
- CBLAS (levels 1, 2 and 3) 3.10.0
- OpenMP 4.5
- OpenACC 2.7

Vectorization diagnosis of compilers:
- gcc 4.8.1 - 11.2
- clang 3.5 - 12.0.1
- icc 19.0 - 2021.1

Note that the output also shows the supported versions of third-party software tools, like compilers and parallel programming application program interfaces.

2. Get the performance optimization report of the whole code

You should always start by invoking the pwreport tool:

$ pwreport --screening canny.c
SCREENING REPORT

Target  Lines of code Analyzed lines Analysis time # actions Effort Cost    Profiling
------- ------------- -------------- ------------- --------- ------ ------- ---------
canny.c 656           252            154 ms        91        264 h  8639€   n/a
------- ------------- -------------- ------------- --------- ------ ------- ---------
Total   656           252            154 ms        91        264 h  8639€   n/a

ACTIONS PER STAGE OF THE PERFORMANCE OPTIMIZATION ROADMAP
Target  Scalar Control Memory Vector Multi Offload
------- ------ ------- ------ ------ ----- -------
canny.c 22     45      8      15     n/a   n/a
------- ------ ------- ------ ------ ----- -------
Total   22     45      8      15     n/a   n/a

TOTAL NUMBER OF LOOPS FOR CODEE AUTO AND GUIDED MODES
                      --------------- # actions ----------------
Codee support # Loops Scalar Control Memory Vector Multi Offload
------------- ------- ------ ------- ------ ------ ----- -------
Auto          1       0      0       0      2      n/a   n/a
Guided        28      20     39      8      6      n/a   n/a
Develop       5       1      5       0      7      n/a   n/a
Roadmap       7       0      0       0      0      n/a   n/a

Target : analyzed directory or source code file
Lines of code : total lines of code found in the target (computed the same way as the sloccount tool)
Analyzed lines : relevant lines of code successfully analyzed
Analysis time : time required to analyze the target
# actions : total actionable items (opportunities, recommendations, defects and remarks) detected
Effort : estimated number of hours it would take to carry out all actions (scalar, control, memory, vector, multi and offload with 1, 2, 4, 8, 12 and 16 hours respectively)
Cost : estimated cost in euros to carry out all the actions, paying the average salary of 56,286€/year for a professional C/C++ developer working 1720 hours per year
Profiling : estimation of overall execution time required by this target

Codee support : Codee support level given for the loop:
  - Auto: the loop can be automatically optimized by Codee auto mode (pwdirectives --auto)
  - Guided: Codee assists  the user in order to optimize the loop
  - Develop: Codee lacks support for the loop, but the feature is under development
  - Roadmap: Codee lacks support for the loop, and the feature is on the long term roadmap

SUGGESTIONS
  Use --level 1|2 to get more details, e.g:
        pwreport --level 2 --screening canny.c

  You can specify multiple inputs which will be displayed as multiple rows (ie. targets) in the table, eg:
        pwreport --screening some/other/dir canny.c

  Use --actions to find out details about the detected actions:
        pwreport --actions canny.c

  You can automatically vectorize every vectorizable loop of one function with:
        pwdirectives --auto --simd omp --in-place canny.c

  Multithreading and offloading actions are filtered by default. Use --include-tags to enable them:
        pwreport --screening --include-tags all canny.c

  You can focus on a specific optimization type by filtering by its tag (scalar, control, memory, vector, multi, offload), eg.:
        pwreport --actions --include-tags scalar canny.c

1 file successfully analyzed and 0 failures in 154 ms

You can see that the first table provides high level metrics of the analysis of your code. It reports how many lines of code it has and how many of them were successfully analyzed, how long it took to do so, how many human-readable actionable items were detected and an estimation of the cost both in terms of hours and money to address all of them. Finally, this table also indicates “n/a”, meaning that there is no profiling information available to Code.

The second table provides a breakdown of the human-readable actions into the six stages of the performance optimization roadmap. The first three stages correspond to sequential optimizations that take advantage of faster scalar processing (Sequential Scalar), simpler control flow (Sequential Control Flow) and more efficient memory usage (Sequential Memory). The latter three stages correspond to performance optimization that exploit a type of parallelism, from vectorization to multithreading and offloading.

The suggestions provided at the bottom are key for the usage of Codee since they will provide you with hints on what your next steps could be. 

Note the “n/a” in the Multithreading and Offloading columns of the second table. This is because Codee disables those actions by default in order to improve the out-of-the-box experience. We can enable this functionality explicitly, as suggested in the third suggestion, by using the flag --include-tags all.

$ pwreport --screening --include-tags all canny.c
SCREENING REPORT

Target  Lines of code Analyzed lines Analysis time # actions Effort Cost     Profiling
------- ------------- -------------- ------------- --------- ------ -------- ---------
canny.c 656           252            154 ms        97        348 h  11388€   n/a
------- ------------- -------------- ------------- --------- ------ -------- ---------
Total   656           252            154 ms        97        348 h  11388€   n/a

ACTIONS PER STAGE OF THE PERFORMANCE OPTIMIZATION ROADMAP
Target  Scalar Control Memory Vector Multi Offload
------- ------ ------- ------ ------ ----- -------
canny.c 22     45      8      15     3     3
------- ------ ------- ------ ------ ----- -------
Total   22     45      8      15     3     3

TOTAL NUMBER OF LOOPS FOR CODEE AUTO AND GUIDED MODES
                      --------------- # actions ----------------
Codee support # Loops Scalar Control Memory Vector Multi Offload
------------- ------- ------ ------- ------ ------ ----- -------
Auto          1       0      0       0      2      0     0
Guided        28      20     39      8      6      3     3
Develop       5       1      5       0      7      0     0
Roadmap       7       0      0       0      0      0     0

Target : analyzed directory or source code file
Lines of code : total lines of code found in the target (computed the same way as the sloccount tool)
Analyzed lines : relevant lines of code successfully analyzed
Analysis time : time required to analyze the target
# actions : total actionable items (opportunities, recommendations, defects and remarks) detected
Effort : estimated number of hours it would take to carry out all actions (scalar, control, memory, vector, multi and offload with 1, 2, 4, 8, 12 and 16 hours respectively)
Cost : estimated cost in euros to carry out all the actions, paying the average salary of 56,286€/year for a professional C/C++ developer working 1720 hours per year
Profiling : estimation of overall execution time required by this target

Codee support : Codee support level given for the loop:
  - Auto: the loop can be automatically optimized by Codee auto mode (pwdirectives --auto)
  - Guided: Codee assists  the user in order to optimize the loop
  - Develop: Codee lacks support for the loop, but the feature is under development
  - Roadmap: Codee lacks support for the loop, and the feature is on the long term roadmap

SUGGESTIONS
  Use --level 1|2 to get more details, e.g:
        pwreport --level 2 --screening --include-tags all canny.c

  You can specify multiple inputs which will be displayed as multiple rows (ie. targets) in the table, eg:
        pwreport --screening some/other/dir --include-tags all canny.c

  Use --actions to find out details about the detected actions:
        pwreport --actions --include-tags all canny.c

  You can automatically vectorize every vectorizable loop of one function with:
        pwdirectives --auto --simd omp --in-place canny.c

  You can focus on a specific optimization type by filtering by its tag (scalar, control, memory, vector, multi, offload), eg.:
        pwreport --actions --include-tags scalar canny.c

1 file successfully analyzed and 0 failures in 154 ms

Now we can finally see all of the actions reported, including multithreading and offloading related actions.

Don’t miss our next blog post. ✉ Subscribe!

The natural next step is to follow the second suggestion and use the --actions analysis. Note that Codee requires the user to perform --actions analysis over a specific target function or loop, and not over the entire source code. This is because otherwise the output would be too large and hard to digest by the user. It is always a good idea to start using the --actions analysis over hotspot functions, as we will see in the next step.

3. Get the performance optimization report of the hotspot

From profiling, we know that the hotspot for this code corresponds to the gaussian_smooth function. You can narrow the analysis to that function by appending :gaussian_smooth to the filename. The pwreport invocation is as follows:

$ pwreport --actions --include-tags all canny.c:gaussian_smooth
ACTIONS REPORT

  FUNCTION BEGIN at canny.c:gaussian_smooth:439:1
    439: void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,

    LOOP BEGIN at canny.c:gaussian_smooth:474:4 (support: guided)
      474:    for(r=0;r<rows;r++){

      LOOP BEGIN at canny.c:gaussian_smooth:475:7 (support: guided)
        475:       for(c=0;c<cols;c++){

        LOOP BEGIN at canny.c:gaussian_smooth:478:10 (support: guided)
          478:          for(cc=(-center);cc<=center;cc++){

          [RMK012] canny.c:478:10 the vectorization cost model states the loop is not a SIMD opportunity because conditional execution renders vectorization inefficient
        LOOP END
        [PWR002] canny.c:442:18 'cc' not declared in the innermost scope possible
        [PWR002] canny.c:447:10 'dot' not declared in the innermost scope possible
        [PWR002] canny.c:448:10 'sum' not declared in the innermost scope possible
      LOOP END
      [PWR002] canny.c:442:11 'c' not declared in the innermost scope possible
      [PWR002] canny.c:442:18 'cc' not declared in the innermost scope possible
      [PWR002] canny.c:447:10 'dot' not declared in the innermost scope possible
      [PWR002] canny.c:448:10 'sum' not declared in the innermost scope possible

      [OPP001] canny.c:474:4 is a multi-threading opportunity
      [OPP003] canny.c:474:4 is an offload opportunity
    LOOP END

    LOOP BEGIN at canny.c:gaussian_smooth:492:4 (support: guided)
      492:    for(c=0;c<cols;c++){

      LOOP BEGIN at canny.c:gaussian_smooth:493:7 (support: guided)
        493:       for(r=0;r<rows;r++){

        LOOP BEGIN at canny.c:gaussian_smooth:496:10 (support: guided)
          496:          for(rr=(-center);rr<=center;rr++){

          [PWR034] canny.c:496:10 avoid strided array access for variable 'tempim' to improve performance
          [RMK010] canny.c:496:10 the vectorization cost model states the loop is not a SIMD opportunity due to strided memory accesses in the loop body
        LOOP END
        [PWR002] canny.c:442:14 'rr' not declared in the innermost scope possible
        [PWR002] canny.c:447:10 'dot' not declared in the innermost scope possible
        [PWR002] canny.c:448:10 'sum' not declared in the innermost scope possible
        [PWR034] canny.c:493:7 avoid strided array access for variable 'smoothedim' to improve performance
      LOOP END
      [PWR002] canny.c:442:8 'r' not declared in the innermost scope possible
      [PWR002] canny.c:442:14 'rr' not declared in the innermost scope possible
      [PWR002] canny.c:447:10 'dot' not declared in the innermost scope possible
      [PWR002] canny.c:448:10 'sum' not declared in the innermost scope possible

      [OPP001] canny.c:492:4 is a multi-threading opportunity
      [OPP003] canny.c:492:4 is an offload opportunity
    LOOP END
  FUNCTION END

METRICS SUMMARY
  Total recommendations:        16
  Total opportunities:           4
  Total defects:                 0
  Total remarks:                 2

SUGGESTIONS

  Use --level 1|2 to get more details, e.g:
        pwreport --level 2 --actions --include-tags all canny.c:gaussian_smooth

  16 recommendations were found in your code, get more information with pwreport:
        pwreport --actions --include-tags pwr canny.c:gaussian_smooth

  4 opportunities for parallelization were found in your code, get more information with pwloops:
        pwloops --include-tags all canny.c:gaussian_smooth

  More details on the defects, recommendations and more in the Knowledge Base:
        
Knowledge base
1 file successfully analyzed and 0 failures in 50 ms

The hotspot analysis succeeds and a report is outputted with the following sections:

  1. ACTIONS REPORT: structured report with actionable insights per function and loop.
  2. CODE COVERAGE: summary of how much code could be analyzed.
  3. METRICS SUMMARY: aggregated summary of the actionable insights detected in the analysis.
  4. SUGGESTIONS: general Codee usage hints.

The CODE COVERAGE report shows that all the code was successfully analyzed and the METRICS SUMMARY shows the different actionable insights detected. As hinted in the SUGGESTIONS section at the end, you can add --level to increase the level of the detail of the ACTIONS REPORT.

4. Dig deeper into the actionable insights for your hotspot

By invoking pwreport with the --level 2 flag, we get a very verbose report. In order to narrow the analysis, we will invoke pwreport for the target loop at line 474. The output is as follows:

$ pwreport --actions --level 2 --include-tags all canny.c:474
ACTIONS REPORT
. . .
  	[OPP001] canny.c:492:4 is a multi-threading opportunity
    	Compute patterns:
      	- 'forall' over the variable 'smoothedim'

    	SUGGESTION: use pwloops to get more details or pwdirectives to generate directives:
      	pwloops canny.c:gaussian_smooth:492:4 --include-tags all
      	pwdirectives --omp multi canny.c:gaussian_smooth:492:4 --in-place

    	More information on: https://www.codee.com/knowledge/opp001

. . .

You can see suggestions on how to use other tools of Codee: use pwloops to get detailed information at the loop-level or pwdirectives to rewrite the source code and create a performance-optimized version automatically. 

Building performance into the code from day one with Codee
Request a demo ›

Particularly, for the hotspot loop of Canny, Codee reports the OPP001 opportunity, which indicates that you can optimize the performance of the loop by applying multi-threading to it. It also points out that you can pwdirectives to rewrite the source code of the loop automatically. Let’s see how to do it.

5. Optimize the performance of your hotspot

Let’s give the latter a try to add multi-threading. First, let’s build and run canny to see how long it takes for the sequential version to execute. You can use the Makefile to do so:

$ make
rm -fr canny testvecs
cc canny.c -fopenmp -O3 -lm -o canny
unzip ../15360_8640.zip
Archive:  ../15360_8640.zip
   creating: testvecs/
   creating: testvecs/input/
  inflating: testvecs/input/15360_8640.pgm  
./canny testvecs/input/15360_8640.pgm 0.5 0.7 0.9
Total time: 11.688

Now copy the command suggested by pwreport (note that using --in-place will modify the file, you can use -o canny_omp.c instead to create a new file):

$ pwdirectives --omp multi canny.c:gaussian_smooth:474:4 --in-place
Results for file 'canny.c':
  Successfully parallelized loop at 'canny.c:gaussian_smooth:474:4' [using multi-threading]:
      [INFO] canny.c:474:4 Parallel forall: variable 'tempim'
      [INFO] canny.c:474:4 Loop parallelized with multithreading using OpenMP directive 'for'
      [INFO] canny.c:474:4 Parallel region defined by OpenMP directive 'parallel'
      [INFO] canny.c:474:4 Make sure there is no aliasing among variables: kernel, tempim
Successfully updated canny.c

Minimum software stack requirements: OpenMP version 3.0 with multithreading capabilities

Note that the hotspot function gaussian_smooth contains two groups of nested loops, and we have just optimized the first one. In order to optimize the second group as well, just execute once again pwreport –actions to discover that there is another opportunity for multithreading available:

$ pwreport --actions --level 2 --include-tags all canny.c:gaussian_smooth
ACTIONS REPORT
  FUNCTION BEGIN at canny.c:gaussian_smooth:439:1
    439: void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
    . . .
    LOOP BEGIN at canny.c:gaussian_smooth:496:4 (difficulty: low)
      . . .       
     [OPP001] canny.c:496:4 is a multi-threading opportunity
        Compute patterns:
          - 'forall' over the variable 'smoothedim'

        SUGGESTION: use pwloops to get more details or pwdirectives to generate directives:
          pwloops canny.c:gaussian_smooth:496:4 --include-tags all
          pwdirectives --omp multi canny.c:gaussian_smooth:496:4 --in-place

        More information on: https://www.codee.com/knowledge/opp001
    . . .
    LOOP END
  . . .
  FUNCTION END

Follow the suggestion again to do the same for that second group of loops:

$ pwdirectives --omp multi canny.c:gaussian_smooth:496:4 --in-place

Results for file 'canny.c':
  Successfully parallelized loop at 'canny.c:gaussian_smooth:496:4' [using multi-threading]:
      [INFO] canny.c:496:4 Parallel forall: variable 'smoothedim'
      [INFO] canny.c:496:4 Loop parallelized with multithreading using OpenMP directive 'for'
      [INFO] canny.c:496:4 Parallel region defined by OpenMP directive 'parallel'
      [INFO] canny.c:496:4 Make sure there is no aliasing among variables: tempim, kernel
Successfully updated canny.c

Minimum software stack requirements: OpenMP version 3.0 with multithreading capabilities

Build and run again to compare the performance:

$ make
rm -fr canny testvecs
cc canny.c -fopenmp -O3 -lm -o canny
unzip ../15360_8640.zip
Archive:  ../15360_8640.zip
   creating: testvecs/
   creating: testvecs/input/
  inflating: testvecs/input/15360_8640.pgm  
./canny testvecs/input/15360_8640.pgm 0.5 0.7 0.9
Total time: 5.942

On a laptop equipped with an AMD Ryzen 7 4800HS CPU (8 cores, 16 threads), the execution went from 11.7 to just 5.9 seconds: almost a 2x speedup!

Building performance into the code from day one with Codee

Request a demo
Contact our team

Filed Under: Technical Tagged With: accelerator processors, best practices, canny, Codee, image processing algorithm, matrix multiplication, multicore, speedup the code

Previous Post
Next Post

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Footer

PRODUCT

Request a demo

Purchase inquiry

Knowledge base

COMPANY

About us

Become a partner

Contact us

Newsletter

FOLLOW US

  • LinkedIn
  • Twitter
  • YouTube

NEWSLETTER

Cambiar | Eliminar

APPENTRA SOLUTIONS S.L
P.º Marítimo, 22b, 15679 Cambre, A Coruña, Spain

Cookie Policy | Privacy policy | Legal Disclaimer

Copyright © 2023 Appentra Solutions, S.L.

We use cookies!
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.
Accept Cookies Read more
Cookies Policy

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. these cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your experience.

CookieTypeDurationDescription
0
__asc030 minutes
__auc01 year
__bs_id01 year
__cfduid11 monthThe cookie is set by CloudFare. The cookie is used to identify individual clients behind a shared IP address d apply security settings on a per-client basis. It doesnot correspond to any user ID in the web application and does not store any personally identifiable information.
__gads01 yearThis cookie is set by Google and stored under the name dounleclick.com. This cookie is used to track how many times users see a particular advert which helps in measuring the success of the campaign and calculate the revenue generated by the campaign. These cookies can only be read from the domain that it is set on so it will not track any data while browsing through another sites.
__lxGr__ses015 minutes
__lxGr__var_654116015 minutes
__lxGr__var_654122015 minutes
__lxGr__var_654124015 minutes
__lxGr__var_654130015 minutes
__lxGr__var_654134015 minutes
__lxGr__var_654146015 minutes
__lxGr__var_654157015 minutes
__lxGr__var_654161015 minutes
__lxGr__var_654163015 minutes
__lxGr__var_654165015 minutes
__lxGr__var_654333015 minutes
__stid01 yearThe cookie is set by ShareThis. The cookie is used for site analytics to determine the pages visited, the amount of time spent, etc.
__stidv01 year
__utma02 yearsThis cookie is set by Google Analytics and is used to distinguish users and sessions. The cookie is created when the JavaScript library executes and there are no existing __utma cookies. The cookie is updated every time data is sent to Google Analytics.
__utmb030 minutesThe cookie is set by Google Analytics. The cookie is used to determine new sessions/visits. The cookie is created when the JavaScript library executes and there are no existing __utma cookies. The cookie is updated every time data is sent to Google Analytics.
__utmc0The cookie is set by Google Analytics and is deleted when the user closes the browser. The cookie is not used by ga.js. The cookie is used to enable interoperability with urchin.js which is an older version of Google analytics and used in conjunction with the __utmb cookie to determine new sessions/visits.
__utmt010 minutesThe cookie is set by Google Analytics and is used to throttle the request rate.
__utmt_onm010 minutes
__utmz06 monthsThis cookie is set by Google analytics and is used to store the traffic source or campaign through which the visitor reached your site.
_abck01 year
_cb01 year
_cb_ls01 year
_cb_svref030 minutes
_chartbeat201 year
_fbp02 monthsThis cookie is set by Facebook to deliver advertisement when they are on Facebook or a digital platform powered by Facebook advertising after visiting this website.
_ga02 yearsThis cookie is installed by Google Analytics. The cookie is used to calculate visitor, session, camapign data and keep track of site usage for the site's analytics report. The cookies store information anonymously and assigns a randoly generated number to identify unique visitors.
_ga_Y5Q8GRTQY902 years
_gat01 minuteThis cookies is installed by Google Universal Analytics to throttle the request rate to limit the colllection of data on high traffic sites.
_gat_bgs01 minute
_gat_gtag_UA_25587466_801 minuteGoogle uses this cookie to distinguish users.
_gat_gtag_UA_84471197_1601 minuteGoogle uses this cookie to distinguish users.
_gat_hearst01 minute
_gat_tDelegDominio01 minute
_gat_tDominio01 minute
_gat_tRollupComscore01 minute
_gat_tRollupDelegacion01 minute
_gat_tRollupGlobal01 minute
_gat_tRollupLvgTotal01 minute
_gat_tRollupNivel101 minute
_gat_UA-5144860-201 minuteThis is a pattern type cookie set by Google Analytics, where the pattern element on the name contains the unique identity number of the account or website it relates to. It appears to be a variation of the _gat cookie which is used to limit the amount of data recorded by Google on high traffic volume websites.
_gid01 dayThis cookie is installed by Google Analytics. The cookie is used to store information of how visitors use a website and helps in creating an analytics report of how the wbsite is doing. The data collected including the number visitors, the source where they have come from, and the pages viisted in an anonymous form.
_kuid_05 monthsThe cookie is set by Krux Digital under the domain krxd.net. The cookie stores a unique ID to identify a returning user for the purpose of targeted advertising.
_li_ss01 month
Necessary
Always Enabled

Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.

CookieTypeDurationDescription
__cfduid11 monthThe cookie is set by CloudFare. The cookie is used to identify individual clients behind a shared IP address d apply security settings on a per-client basis. It doesnot correspond to any user ID in the web application and does not store any personally identifiable information.
cookielawinfo-checkbox-necessary011 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-necessary01 hourThis cookie is set by GDPR Cookie Consent plugin. The purpose of this cookie is to check whether or not the user has given the consent to the usage of cookies under the category 'Necessary'.
cookielawinfo-checkbox-non-necessary011 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Non Necessary".
cookielawinfo-checkbox-non-necessary01 hourThis cookie is set by GDPR Cookie Consent plugin. The purpose of this cookie is to check whether or not the user has given their consent to the usage of cookies under the category 'Non-Necessary'.
DSID11 hourTo note specific user identity. Contains hashed/encrypted unique ID.
JSESSIONID1Used by sites written in JSP. General purpose platform session cookies that are used to maintain users' state across page requests.
PHPSESSID0This cookie is native to PHP applications. The cookie is used to store and identify a users' unique session ID for the purpose of managing user session on the website. The cookie is a session cookies and is deleted when all the browser windows are closed.
pmpro_visit0The cookie is set by the Paid Membership Pro plugin. The cookie is used to manage user memberships.
viewed_cookie_policy011 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
viewed_cookie_policy01 hourThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Analytics

Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.

CookieTypeDurationDescription
__gads01 yearThis cookie is set by Google and stored under the name dounleclick.com. This cookie is used to track how many times users see a particular advert which helps in measuring the success of the campaign and calculate the revenue generated by the campaign. These cookies can only be read from the domain that it is set on so it will not track any data while browsing through another sites.
__stid01 yearThe cookie is set by ShareThis. The cookie is used for site analytics to determine the pages visited, the amount of time spent, etc.
_ga02 yearsThis cookie is installed by Google Analytics. The cookie is used to calculate visitor, session, camapign data and keep track of site usage for the site's analytics report. The cookies store information anonymously and assigns a randoly generated number to identify unique visitors.
_gat_gtag_UA_25587466_801 minuteGoogle uses this cookie to distinguish users.
_gat_gtag_UA_84471197_1601 minuteGoogle uses this cookie to distinguish users.
_gid01 dayThis cookie is installed by Google Analytics. The cookie is used to store information of how visitors use a website and helps in creating an analytics report of how the wbsite is doing. The data collected including the number visitors, the source where they have come from, and the pages viisted in an anonymous form.
ad-id17 monthsProvided by amazon-adsystem.com for tracking user actions on other websites to provide targeted content
demdex05 monthsThis cookie is set under the domain demdex.net and is used by Adobe Audience Manager to help identify a unique visitor across domains.
GPS030 minutesThis cookie is set by Youtube and registers a unique ID for tracking users based on their geographical location
pardot0The cookie is set when the visitor is logged in as a Pardot user.
tk_lr01 yearThis cookie is set by JetPack plugin on sites using WooCommerce. This is a referral cookie used for analyzing referrer behavior for Jetpack
tk_or05 yearsThis cookie is set by JetPack plugin on sites using WooCommerce. This is a referral cookie used for analyzing referrer behavior for Jetpack
tk_r3d03 daysThe cookie is installed by JetPack. Used for the internal metrics fo user activities to improve user experience
Advertisement

Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.

CookieTypeDurationDescription
_fbp02 monthsThis cookie is set by Facebook to deliver advertisement when they are on Facebook or a digital platform powered by Facebook advertising after visiting this website.
_kuid_05 monthsThe cookie is set by Krux Digital under the domain krxd.net. The cookie stores a unique ID to identify a returning user for the purpose of targeted advertising.
ad-privacy15 yearsProvided by amazon-adsystem.com for tracking user actions on other websites to provide targeted content to the users.
ATN12 yearsThe cookie is set by atdmt.com. The cookies stores data about the user behavior on multiple websites. The data is then used to serve relevant advertisements to the users on the website.
dpm05 monthsThe cookie is set by demdex.net. This cookie assigns a unique ID to each visiting user that allows third-party advertisers target that users with relevant ads.
everest_g_v201 yearThe cookie is set under eversttech.net domain. The purpose of the cookie is to map clicks to other events on the client's website.
fr12 monthsThe cookie is set by Facebook to show relevant advertisments to the users and measure and improve the advertisements. The cookie also tracks the behavior of the user across the web on sites that have Facebook pixel or Facebook social plugin.
IDE12 yearsUsed by Google DoubleClick and stores information about how the user uses the website and any other advertisement before visiting the website. This is used to present users with ads that are relevant to them according to the user profile.
khaos01 yearThis cookie is set by rubiconproject.com. The cookie is used to store user data in an anonymous form such as the IP address, geographical location, websites visited, and the ads clicked. The purpose of the cookie is to tailor the ads displayed to the users based on the users movement on other site in the same ad network.
ljt_reader01 yearThis is a Lijit Advertising Platform cookie. The cookie is used for recognizing the browser or device when users return to their site or one of their partner's site.
mako_uid01 yearThis cookie is set under the domain ps.eyeota.net. The cookies is used to collect data about the users' visit to the website such as the pages visited. The data is used to create a users' profile in terms of their interest and demographic. This data is used for targeted advertising and marketing.
mc01 yearThis cookie is associated with Quantserve to track anonymously how a user interact with the website.
NID16 monthsThis cookie is used to a profile based on user's interest and display personalized ads to the users.
p201 weekThe cookies is set by ownerIQ for the purpose of providing relevant advertisement.
personalization_id02 yearsThis cookie is set by twitter.com. It is used integrate the sharing features of this social media. It also stores information about how the user uses the website for tracking and targeting.
PUBMDCID02 monthsThis cookie is set by pubmatic.com. The cookie stores an ID that is used to display ads on the users' browser.
si05 yearsThe cookies is set by ownerIQ for the purpose of providing relevant advertisement.
TDCPM01 yearThe cookie is set by CloudFare service to store a unique ID to identify a returning users device which then is used for targeted advertising.
TDID01 yearThe cookie is set by CloudFare service to store a unique ID to identify a returning users device which then is used for targeted advertising.
test_cookie015 minutesThis cookie is set by doubleclick.net. The purpose of the cookie is to determine if the users' browser supports cookies.
tuuid01 yearThis cookie is set by .bidswitch.net. The cookies stores a unique ID for the purpose of the determining what adverts the users have seen if you have visited any of the advertisers website. The information is used for determining when and how often users will see a certain banner.
tuuid_lu01 yearThis cookie is set by .bidswitch.net. The cookies stores a unique ID for the purpose of the determining what adverts the users have seen if you have visited any of the advertisers website. The information is used for determining when and how often users will see a certain banner.
uid01 monthThis cookie is used to measure the number and behavior of the visitors to the website anonymously. The data includes the number of visits, average duration of the visit on the website, pages visited, etc. for the purpose of better understanding user preferences for targeted advertisments.
uuid01 monthTo optimize ad relevance by collecting visitor data from multiple websites such as what pages have been loaded.
VISITOR_INFO1_LIVE15 monthsThis cookie is set by Youtube. Used to track the information of the embedded YouTube videos on a website.
Technical

Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.

CookieTypeDurationDescription
__utma02 yearsThis cookie is set by Google Analytics and is used to distinguish users and sessions. The cookie is created when the JavaScript library executes and there are no existing __utma cookies. The cookie is updated every time data is sent to Google Analytics.
__utmb030 minutesThe cookie is set by Google Analytics. The cookie is used to determine new sessions/visits. The cookie is created when the JavaScript library executes and there are no existing __utma cookies. The cookie is updated every time data is sent to Google Analytics.
__utmc0The cookie is set by Google Analytics and is deleted when the user closes the browser. The cookie is not used by ga.js. The cookie is used to enable interoperability with urchin.js which is an older version of Google analytics and used in conjunction with the __utmb cookie to determine new sessions/visits.
__utmt010 minutesThe cookie is set by Google Analytics and is used to throttle the request rate.
__utmz06 monthsThis cookie is set by Google analytics and is used to store the traffic source or campaign through which the visitor reached your site.
_gat01 minuteThis cookies is installed by Google Universal Analytics to throttle the request rate to limit the colllection of data on high traffic sites.
_gat_UA-5144860-201 minuteThis is a pattern type cookie set by Google Analytics, where the pattern element on the name contains the unique identity number of the account or website it relates to. It appears to be a variation of the _gat cookie which is used to limit the amount of data recorded by Google on high traffic volume websites.
AMP_TOKEN01 hourThis cookie is set by Google Analytics - This cookie contains a token that can be used to retrieve a Client ID from AMP Client ID service. Other possible values indicate opt-out, inflight request or an error retrieving a Client ID from AMP Client ID service.
audit01 yearThis cookie is set by Rubicon Project and is used for recording cookie consent data.
bcookie02 yearsThis cookie is set by linkedIn. The purpose of the cookie is to enable LinkedIn functionalities on the page.
lang0This cookie is used to store the language preferences of a user to serve up content in that stored language the next time user visit the website.
lidc01 dayThis cookie is set by LinkedIn and used for routing.
mailchimp_landing_site04 weeksThe cookie is set by the email marketing service MailChimp.
na_id01 yearThis cookie is set by Addthis.com to enable sharing of links on social media platforms like Facebook and Twitter
ouid01 yearThe cookie is set by Addthis which enables the content of the website to be shared across different networking and social sharing websites.
pid01 yearHelps users identify the users and lets the users use twitter related features from the webpage they are visiting.
PugT01 monthThis cookie is set by pubmatic.com. The purpose of the cookie is to check when the cookies were last updated on the browser in order to limit the number of calls to the server-side cookie store.
sid0This cookie is very common and is used for session state management.
test_cookie011 monthsThis cookie is set by doubleclick.net. The purpose of the cookie is to determine if the users' browser supports cookies.
YSC1This cookies is set by Youtube and is used to track the views of embedded videos.
Save & Accept
X