Quantcast
Channel: Intel Developer Zone Articles
Viewing all 3384 articles
Browse latest View live

2017 Intel® Level Up Contest Closed

$
0
0

Intel® Level Up Contest

Thank you for your interest in the 2017 Intel® Level Up Game Dev Contest. The contest closed on May 9, 2017.

 


Modern VR is ‘like the dog who catches a car but doesn’t know what to do with it’

$
0
0

Kim Pallister, VR expert at Intel, and sci-fi author Austin Grossman at GamesBeat Summit 2017

The modern virtual reality market is new, but the idea of virtual worlds has existed in fiction for decades.

Austin Grossman is a sci-fi author who has written books such as the techno-thriller You: A Novel. He also helped write games like PC classics Deus Ex and System Shock as well as the more recent Dishonored series. At the GamesBeat Summit today in Berkley, California, Grossman discussed in an on-stage interview with Kim Pallister, VR expert at Intel, how sci-fi stories from our past can tell us about the future of virtual reality — and how we’re struggling how to deal with it.

Grossman brought up novels like Snow Crash and Ready Player One, which both featured VR social spaces. These ideas used to be science fiction, but modern virtual reality devices and online games are maker them closer to reality. But Grossman says that we’re like the dog who catches a car but doesn’t know what to do with it.

VR isn’t just an entertainment experience that people use for 10 minutes at a time, Grossman said, in novels. It is an integral part of society that people use for work as much as play. It’s also a tool used to escape from dystopian nightmares. In Ready Player One, many people are living in ghettos of skyscrapers made of trailer park homes. Its protagonist spends as much time in virtual reality as possible, using it to have access to things he doesn’t have in the real world: friends, education, and adventures.

This could present a danger to our VR future. What if people use the coming virtual worlds to escape the real one? Could we potentially forsake the planet and our ties to it in favor of a more palpable digital illusion?

So, the future of VR presented in fiction could be an unsettling one. But fiction hasn’t gotten everything right. In The Matrix, people need to be in pods or other constrictive devices to be connected to virtual worlds (and that’s besides the fact that most humans were imprisoned and having their energy sucked out by evil robots). But we aren’t using neural interfaces.

“It’s a wonderful thing that we got wrong,” Grossman said. Actual VR has players moving around. He says that this makes VR more exciting and less of a terrifying dystopia.

Grossman noted that world-building is the key skill needed for making enjoyable VR experiences. To make a world for a novel, that takes him two or three years of planning. But for modern virtual reality games, more work goes into designing and programming the experience. Less attention is given to narrative, characters, and history. These are the things that make people fall in love with and to live in a fictional world.

Licensing IP is kind of a cheat, Grossman says. It gives you an immediate world that audiences love. VR designers need to make new worlds of its own. The recent Star Trek: Bridge Crew is a good example of this. Beyond the gameplay, people enjoy the game just because it lets them be in Star Trek.

Virtual reality has the potential to change people and how they relate to each other. Forcing us to interact with others in unique ways. But Grossman noted that he also looks forward to having VR teach him. He anticipates full-body-tracking, since a VR program could then teach him how to dance. That certainly sounds more pleasant than having machine overlords plugging us into a placating VR world while they suck energy from our imprisoned bodies.

Create Draft Article

Publish Draft Article

Test Moderation and Editing Published

Test Moderation and Editing

Artificial Intelligence Powers Clinical Trials

$
0
0

Clinical Trials

Clinical trials (CT) enable us to understand, diagnose, prevent, and treat diseases. Clinical research has led to making diabetes manageable, and prolonged the lives of AIDS and cancer patients. CT is a fundamental tool of modern medicine; it is the cornerstone of the drug development process.


Figure 1: Clinical trial process

The essence of conducting clinical trials is to evaluate the efficacy of new treatments and therapies. On average, it takes about 10 to 15 years to convey a medication from introductory revelation to the hands of patients, and can cost billions of dollars. Artificial intelligence (AI) can significantly reduce both the time and the cost by more than half. The rate of AI in these procedures permits organizations to create drugs with more precision, as compared to manual methodology. Experiments and analysis that would take human researchers weeks and months can be effectively conducted by AI within minutes.

A Historical Perspective

For centuries, medical studies and clinical approaches have been a combination of religious beliefs, magical perspectives, medicinal herbs, and some science.

Eighteenth Century

Back in 1796, smallpox was killing in the thousands, and tormenting others still alive with constant fear. Everyone from the rich to the poor was affected. While smallpox was killing people, Edward Jenner was busy making observations that milkmaids who had contracted cowpox, possibly from infected udders of cows, seemed to be immune to smallpox.

After collecting similar data points over several years, he performed a clinical trial. He scraped a pustule from a milkmaid, Sarah Nelmes, who had cowpox, and inserted the matter into a cut on the arm of his gardener’s son, a young boy called James Phipps. Six weeks later, he inoculated the boy with the smallpox virus. Jenner concluded that his hypothesis was correct when James Phipps did not get smallpox.

The word vaccination comes from vacca, Latin for cow. Jenner’s trials led to the discovery of vaccination. Jenner later conducted a mass vaccination, which prevented smallpox. This simple trial conquered epidemics from typhoid, to polio, to measles in later years. A clinical trial had saved thousands of lives!

Nineteenth Century

Lightner Witmer developed practical work in clinical psychology at the University of Pennsylvania. Clinical psychology aims at preventing and relieving psychological distress and promoting personal development. It involves science and clinical knowledge to understand human patterns. Patients would have their skull shape (phrenology) and face (physiognomy) examined for the doctor to study their personality.

Such scientific data analysis methods and predictions based on information for an individual patient grew steadily in university laboratories by the late 1800s. Mental distress was then in the domain of psychiatrists,while psychologists nurtured the notion of non-curable disorders based on the size and shape of human anatomy as pure science. This changed when Lightner Witmer, then head of the psychology department at the University of Pennsylvania, leveraged the knowledge accumulated thus far to treat a young boy who had trouble with spelling. In 1896 he opened the first psychological clinic at Penn dedicated to helping children with disabilities, and coined the term clinical psychology, defined as the study of individuals, by observation or experimentation, with the intention of promoting change.

An effective use of insights hidden in data derived from patients had successfully differentiated treatable psychological issues from non-curable mental disorders. In fact, two clinical intelligence tests, Army Alpha (verbal skills) and Army Beta (nonverbal skills) were conducted on large groups of recruits during World War I, the success of which led to assessments becoming the core discipline of clinical psychology, eventually leading to treatments.

Clinical trials have continued to evolve since then, and have proven to be a miracle medical invention that has led to numerous lifesaving medicines we know today.

Clinical Trials Today

The complex drug pipeline process poses an enormous challenge: To move through expensive and time-consuming clinical trials efficiently and rapidly.

A core part of clinical evaluation involves the recruitment and selection of eligible patients who go through training programs for relevant clinical trials. To select and recruit eligible patients for clinical trials, clinicians manually analyze medical big data (MBD) and face multiple challenges consisting of the amount of medical data (volume), the number of types of medical data (variety), and the speed with which to process medical data (velocity) to determine inclusion of a patient into a clinical trial.


Figure 2: Clinical trial patient

Challenges

  1. Volunteer based: A clinical trial relies heavily on volunteers willing to participate in studies.
  2. Selection process: This process proves difficult to quickly analyze medical big data against a list of eligibility criteria, risking 60 percent of the chances of a miss to select eligible patients for clinical trials. After spending a considerable amount of time in the selection process, only one in hundreds of new treatments and therapies that achieve Phase I clinical trials is reported to wind up in a genuine treatment.
  3. Cost: The associated cost is estimated at USD 124 million over a decade to complete per new drug per candidate, with half of this time spent in the recruitment of patients, clinical investigators, and in setting the environment for controlled clinical trials. A good example can be found in the study of multicenter randomized controlled trials, where clinical researchers spent about 86.8 staff hours, and over USD 100 in the recruitment of each randomized participant.
  4. Precision: Each examination is complex and could require many individuals to complete it. Besides, each patient is different.
  5. Long-term investment: Reported financial figures in medical journals support the argument that clinical trials involve a long-term investment, with an estimated cost of USD 12 billion on average, and take somewhere between 10 and 15 years to convey new treatments and therapies to the global market. Whereas the actual cost of how much the healthcare and pharmaceutical industries spend on drug development and in conveying new treatments and therapies to the world stage remains debatable, earlier research estimates that it costs somewhere around USD 161 million to USD 2 billion to convey new treatments and therapies to the market. Despite the variations in financial terms, the cost of clinical trials has been reported to have risen substantially, at the rate of 7.4 percent, which is higher than the estimated inflation rate for the past two decades.


Figure 3: Source: The Medical Futurist*

Though statistics have enabled us to design experiments precisely and to minimize errors in decision making, AI has the capacity to conduct such data analysis at the next level, enabling us to leverage not just a few hundred pieces of patient data, but millions. AI enables researchers to crunch enormous amounts of data within days or weeks, thereby reducing the heavy cost incurred in the pharmaceutical creation process. The result can also be customized to the individual, considering their own body's needs.

So, What is Artificial Intelligence?

At an abstract level, artificial intelligence is considered a science that is concerned with the computational understanding of intelligent behavior, with the development of medical artifacts that exhibit such behavior. This behavior consists of the ability of the computer to simulate human-level cognitive performance such as visual perception, speech recognition, decision making, and language translation.

Clinical Trials Powered by Artificial Intelligence

The rising cost of clinical trials and the difficulties involved in developing methodologies to acquire, analyze, and extract knowledge from medical big data in solving complex clinical problems accounts for the advancement in medical artificial intelligence (MAI).

Complementing people’s intelligence with machine intelligence, this augmented intelligence has an exponentially high impact. Machine learning can assist clinicians in their everyday clinical tasks, such as data manipulation and knowledge extraction, diagnosis formulation and the making of therapeutic decisions to predict clinical outcomes, and to improve the quality and lower the cost of clinical trials for better patient care.

Patient Recruiting and Data Collection

Most clinical trials today are led without direct information from patients. Most information is being collected by third-party suppliers amid patient visits. With the invention of mobile, Internet of Things (IoT), and especially wearables, billions of individuals are now conveying important information effortlessly. This phenomenon offers a way to capture relevant information from patients in a continuous and convenient way. With the touch of a button, patients can choose to directly share their information for clinical trials over their mobile devices anywhere and everywhere. Additionally, the information captured is much more contextual, precise, and high quality; something we couldn’t even imagine with manual clinical trials.

Continuous Improvement

Clinical trial processing systems are gradually moving to the cloud, with millions of mobile data points transmitting information, and custom frameworks analyzing the data. This lends a way to run continuous and self-learning trials with greater precision.

Shared Resource Pool with Crowd Sourcing

Patient data can now be shared among multiple clinics through the cloud infrastructure, making it more enticing for patients to participate in trials across the globe.

Ensure Adherence

Given that the local recordings made over mobile devices are continuously transmitted to the cloud, it is now possible for clinics to catch anomalies in drug intake patterns among patients, in a real-time manner, and to even remind the patient if they forget to take their medication.

Predict Drug Effectiveness

Not every human has the same body type; hence, different people can react differently to the same medication. Computerized reasoning is an effective method for anticipating drug results, since it treats a human gene with the entirety of all the collaborating qualities. With AI it is conceivable to predict which patients with a particular disease would benefit the most with a drug.

Applications and Success Stories

Web-Based Selection Process

The application of artificial intelligence in clinical trials is enormous. Experts have created a web-based system that correctly selects and assigns cancer patients to clinical trials within 15 to 30 minutes and takes between 10 and 20 minutes to add new trials. The system is built to accommodate an increase in the number of patients selected for clinical trials, and suggests additional medical tests, while finding the most efficient test-ordering sequence that reduces the cost of recruitment.

ATACH-II*—A Mobile App

Application of artificial intelligence in clinical trials and medical research continues to grow. In a Phase-III clinical trial funded by the National Institute of Neurological Disorders and Stroke, the antihypertensive treatment in acute cerebral hemorrhage (ATACH-II*), in collaboration with MentorMate*, designed a mobile phone app called the ATACH-II app. The app provides assistance with pre-screening, patient eligibility assessment, and randomization in a five-year multi-center, randomized, controlled, Phase-III trial to evaluate the efficacy of early, intensive antihypertensive treatment using intravenous nicardipine for acute hypertension in subjects with spontaneous supratentorial ICH.

In a Phase-II clinical trial conducted at 20 centers across the United States, the UK, Canada, and Germany, the Clot Lysis Evaluating Accelerated Resolution of Intraventricular Hemorrhage (CLEAR-IVH) trial investigators adopted the ATACH-II mobile phone app. The study recruited 52 patients diagnosed with intraventricular hemorrhage (IVH) with third or fourth ventricle obstruction. Each participant was given a thrombolytic, recombinant tissue plasminogen activator (tPA), via an extra ventricular catheter (EVD), in one of three dosing regimens over a three-day period.

AiCure*—Real-Time Non-Adherence Mobile Platform

Research shows that over 20 percent of all clinical trials fail because of non-adherence. AiCure* has developed a powerful, scalable, and real-time advanced non-adherence mobile technology platform that visually confirms medication ingestion. AiCure’s clinically validated platform combines the power of artificial intelligence with deep learning, computer vision, machine learning, and predictive analytics to make sure the right patient is taking the right medication at the right time. The real-time data will assist healthcare and pharmaceutical companies involved in conducting clinical trials to evaluate the efficacy of new treatments and therapies.

Radiology

A skilled radiologist can use systems like AI tools to run tests, and focus on subjective, common sense, human decision making.

IBM Watson* for Oncology


Figure 4: IBM Watson* Analytics

After a patient’s tumor is sequenced by Quest Diagnostics*,Watson* analyzes the genetic alterations found to help identify potentially treatable mutations. This analysis can help oncologists identify targeted therapies for each patient’s individual cancer.

A Promising Future

AI is still in the infant stage of development and will not be able to replace a doctor.

Due to AI’s ability to understand natural language such as clinical notes, along with structured data such as dates and numbers, and the ability to generate hypotheses based on evidence, it is being considered as the Artificial-Intelligence-Powers-Clinical-Trials-Promising-Futurefourth industrial revolution, for which the healthcare and pharmaceutical industries are seen as the biggest beneficiaries.

Artificial intelligence holds even greater promise, not only in transforming clinical research, but also in reducing the cost associated with disease management, successful ageing, and the discovery and development of new medical innovations. For example, it cost USD 200 billion and €125 billion to manage non-communicable diseases in America and Europe, respectively, per year, while in the United States alone it costs three to five times more to provide support for successful ageing for someone aged 65 and over than for someone younger, a cost which is expected to decrease significantly with AI!

Additional Web Resources

https://www.cs.cmu.edu/~eugene/research/full/trial-knowledge.pdf

https://www.sciencedaily.com/releases/2016/04/160427095057.htm

https://www.nhlbi.nih.gov/studies/clinicaltrials

http://www.appliedclinicaltrialsonline.com/three-ways-clinical-trials-will-be-transformed-fourth-industrial-revolution?pageID=1

http://www.clinicalleader.com/doc/clinical-news-roundup-artificial-intelligence-ready-to-run-clinical-trials-0001

http://www.cbsnews.com/news/artificial-intelligence-making-a-difference-in-cancer-care/

http://www.thenakedscientists.com/articles/interviews/story-smallpox

Artificial Intelligence Resource

$
0
0

Intel® Student Developer Program

Welcome and Agenda Talk at UC Berkeley Student Workshop for AI
Bob Duffy welcomes students and reviews the program agenda for the student AI workshop.

Intel® Student Developer AI Workshop—University of California Berkeley
Sneak peek into the Artificial Intelligence workshops hosted by Intel at Universities across the globe.

The Human Side of AI: Affective Computing
Affective Computing can make us aware of our emotional state, helping us take better decisions, help us to help others, or help machines make decisions to enrich our lives. There is another exciting use for emotional data: Machine Learning.

From Smart to Intelligent Vehicles Through Affective Computing
Affective Computing is a capability by which devices understand human emotions and use that understanding to take actions. In this video we look at an example of what can be done with emotional data while you are driving.

Affective Computing in the Home
Affective Computing is a capability by which devices understand human emotions and take actions based on that understanding. In this we look at what can be done with emotional data inside your home.

Affective Computing in the Classroom
Affective Computing helps devices understand human emotions and take actions that can benefit the user. This technology can even be used in a classroom setting. In this video we look at an example based on the work by members of Intel Labs.

Can Technology Replace The Eye?
Data is Much More Than Numbers. Data is the tool we use to communicate a story effectively. Data is the tool that enables us to make informed decisions.

Clinical Trial Patient Screening via Genome Analysis
Genome sequencing and analysis increases patient screening accuracy.

How to Get Started Developing for Automated Driving
From safe roads to enjoyable commutes, automated driving is poised to change lives and society for the better.

Predicting Patient Costs
Session from the second Machine Learning Meetup in Portland, Oregon.

How to Get Started as a Developer in AI
The promise of artificial intelligence has captured our cultural imagination since at least the 1950s—inspiring computer scientists to create new and increasingly complex technologies.

Scaling to Meet the Growing Needs of AI
Scaling distributed machine learning is challenging as it pushes the limits of available data and model parallelism.

An Artificial Intelligence Primer for Developers
Intel is not merely invested in the growth of AI, we are committed to fueling the AI revolution, making it one of our top priorities.

Intel’s New Processors: A Machine-learning Perspective
This talk discusses the usage of Intel’s new server processors for various machine-learning tasks.

The Shallow End of Deep Learning
Watch Ted Willke’s presentation about deep learning
from the first Intel Machine Learning meetup.

What is Saffron* Technology?
This technology enables customers to make better decisions through its natural intelligence platform.

ML-Bench 1.0 Constructing and Analyzing a Machine-Learning Benchmark
This talk describes the analysis method used for building this machine-learning benchmark.

Security and Machine Learning in an Open Source Community
John Whiteman discusses security and machine learning.

Pushing Machine Learning to a New Level
Pushing Machine Learning to a New Level with Intel® Xeon® processors and Intel® Xeon Phi™ processors.

Superior Performance Commits Kyoto University to CPUs Over GPUs
The Kyoto University team recognized that the performance of the open source Theano* C++ multi-core code could be significantly improved.

Tencent* Uses Machine Learning for In-Game Purchase Recommendation System on Intel Xeon Processors
Tencent* uses an in-game purchase recommendation system employing the machine learning method to enhance the online gaming user experience.

Introducing the new Packed APIs for GEMM
Introducing Packed APIs for GEMM Matrix-matrix multiplication (GEMM) is a fundamental operation in many scientific, engineering, and learning applications.

What is All the Buzz About Machine Learning
Machine learning is changing the balance of labor between the decision-making role of humans, and the number-crunching roles of computers. Pradeep Dubey discusses the excitement behind the theories and practices that machine learning is redefining.

Machine Learning Introduction: Regression and Classification
This video examines two of the main problems with machine learning, regression, and classification.

Intel® Xeon Phi™ processors Delivers Competitive Performance for Deep Learning—And Getting Better Fast
Baidu’s recently announced deep learning benchmark, DeepBench, documents performance for the lowest-level compute and communication primitives for deep learning applications.


Using a Deep Learning Approach to Model Behavior in MOOCs
Berkeley graduate student Steven Tang shows his approach to modeling behavior in Massive Open Online Courses.

From Smart to Intelligent Vehicles Through Affective Computing
Affective Computing is a capability by which devices understand human emotions and use that understanding to take actions. In this video we look at an example of what can be done with emotional data while you are driving.

Deep Learning for Virtual Cancer Screening
Demo: Deep learning for virtual screening.

Accelerating Neural Networks with Binary Arithmetic
The original article is published on Intel® Nervana™ AI solution site: Accelerating Neural Networks with Binary Arithmetic. Please go to Nervana Homepage (nervanasys.com) to learn more on Intel Nervana’s deep learning technologies.

Intel® Xeon Phi™ Delivers Competitive Performance for Deep Learning—And Getting Better Fast
Baidu’s recently announced deep learning benchmark, DeepBench, documents performance for the lowest-level compute and communication primitives for deep learning (DL) applications.

Superior Performance Commits Kyoto University to CPUs Over GPUs
The Kyoto University team recognized that the performance of the open source Theano* C++ multi-core code could be significantly improved.

Distributed Training of Deep Networks on Amazon Web Services* (AWS)
In this article, we provide the steps to set up the AWS CloudFormation* environment to train deep networks using the Caffe* network.

A Brief Overview of Deep Learning Using Intel® Architectures
Deep learning attempts to model various levels of abstraction within data. There are various tools to train and deploy deep networks, and Intel is actively working with the deep learning community to optimize many of the frameworks to significantly improve computational performance on Intel® architectures.


Introduction to Deep Learning with Intel® Nervana™ AI solution and the neon™ framework
Learn about Intel® Nervana™ AI solution deep learning technology including the neon™ framework.

Deep Learning Demos of the Intel® Nervana™ AI solution Platform Using neon™ framework
Walkthrough of Neon demos using Jupyter* notebooks such as MNIST and sentiment analysis with LSTM.

Hands-on Deep Learning Workshop: Intel® Nervana™ AI solution Artificial Intelligence—Part 1
In this talk, we will give an overview of the Intel® Nervana™ DL platform and get some hands-on experience using this platform to train and execute deep learning models.

Hands-on Deep Learning Workshop: Intel® Nervana™ AI solution Artificial Intelligence—Part 2
In this talk, we will give an overview of the Intel® Nervana™ AI solution DL platform and get some hands-on experience using this platform to train and execute deep learning models.

Intel® Nervana™ AI solution’s End-to-End Speech Recognition with neon™
This Meetup covers the basic ideas that go into building an end-to-end speech recognition system trained entirely using deep learning techniques. You will have understanding of the high level concepts that go into training a speech recognition engine in an end-to-end fashion.

Intel® Nervana™ AI solution Engine Delivers Deep Learning at Ludicrous Speed!
Intel® Nervana™ AI solution is currently developing the Intel® Nervana™ Solution Engine, an application specific integrated circuit (ASIC) that is custom designed and optimized for deep learning.

Distributed, Docker*-ized Deep Learning with Intel® Nervana™ technology, neon™ framework, and Pachyderm*
The recent advances in machine learning and artificial intelligence are amazing! It seems like we see something groundbreaking every day, from self-driving cars, to AIs learning complex games.

How to Install the neon™ framework on Ubuntu*
This article presents a simple step-by-step way to install the neon™ framework in Ubuntu* 14.04 using the Anaconda* Python* distribution.

Transfer Learning Using neon™
Please check the original article at Nervana’s site  to learn more about this topic and more on Intel Nervana’s deep learning frameworks.


Webinar: Deep Learning 101
This webinar describes various deep learning usages and highlights those in which Caffe* is used.

Caffe* Optimized for Intel® Architecture: Applying Modern Code Techniques
This paper demonstrates a special version of Caffe*—a deep learning framework originally developed by the Berkeley Vision and Learning Center (BVLC)—that is optimized for Intel® architecture.

Distributed Training of Deep Networks on Amazon Web Services* (AWS)
In this article, we provide the steps to set up the AWS CloudFormation* environment to train deep networks using the Caffe* network.

How to Install Caffe* Optimized for Intel® Architecture
This video shows you how to install Caffe* Optimized for Intel® architecture.

What is Intel® Optimized Caffe*
Caffe* is a deep learning framework that is useful for convolutional and fully connected networks, and recently recurrent neural networks were added. There are various forks of Caffe branches that cover a variety of tasks.

Recipe: Optimized Caffe* for Deep Learning on Intel® Xeon Phi™ processor x200
The computer learning code Caffe* has been optimized for Intel® Xeon Phi™ processors. This article provides detailed instructions on how to compile and run this Caffe* optimized for Intel® architecture to obtain the best performance on Intel Xeon Phi processors.

Training and Deploying Deep Learning Networks with Caffe* Optimized for Intel® Architectures
Caffe* is a deep learning framework developed by the Berkeley Vision and Learning Center (BVLC). Caffe optimized for Intel architecture is currently integrated with the latest release of Intel® Math Kernel Library (Intel® MKL).

Caffe* Training on Multi-node Distributed-memory Systems Based on Intel Xeon Processor E5 Family
Caffe is a deep learning framework developed by the Berkeley Vision and Learning Center (BVLC) and one of the most popular community frameworks for image recognition.

Single Node Caffe Scoring and Training on Intel® Xeon E5-Series Processors
Deep Neural Network (DNN) applications grow in importance in various areas including internet search engines and medical imaging.

Intel and Facebook* Collaborate to Boost Caffe2 Performance on Intel CPU’s
Every day, the world generates more and more information—text, pictures, videos and more. In recent years, artificial intelligence and deep learning have improved several applications that help people better understand this information.


BigDL: Distributed Deep Learning on Apache Spark*
As the leading framework for Distributed ML, the addition of deep learning to the super-popular Spark framework becomes increasingly important.

Intel’s Optimized Tools and Frameworks for Machine Learning and Deep Learning
This article gives an introduction to Intel’s optimized machine learning and deep learning tools and frameworks.

Getting Started with Intel® Software Optimization for Theano* and Intel® Distribution for Python*
Theano* is a Python* library developed at the LISA lab to define, optimize, and evaluate mathematical expressions, including the ones with multi-dimensional arrays (numpy.ndarray).

Distributed Machine Learning on Apache Spark*
Radhika Rangarajan, Engineering Program Manager at Intel, discusses distributed machine learning on Apache Spark*.

TensorFlow* Optimizations on Modern Intel® Architectures
This paper introduces the Artificial Intelligence (AI) community to TensorFlow* optimizations on Intel® Xeon® processors and Intel® Xeon Phi™ processor-based systems.

Introduction to BigDL on Apache Spark* Part1
Addressing the need for a unified platform for big data analytics and deep learning, Intel recently released BigDL, an open source distributed deep learning library for Apache Spark*.

BigDL: Bring Deep Learning to the Fingertips of Big Data Users and Data Scientists
This blog provides an overview of recent enhancements available in the BigDL 0.1.0 release (as well as in the upcoming 0.1.1 release).

Deploying BigDL on Microsoft’s Azure* Data Science Virtual Machine
To make it easier to deploy BigDL, we created a “Deploy to Azure” button on top of the Linux* (Ubuntu*) edition of the Data Science Virtual Machine (DSVM).

BigDL—Scale-out Deep Learning on Apache Spark* Cluster
Learn how to install and use BigDL for training and testing some of the commonly used deep neural network models on Apache Spark.


Intel’s Optimized Tools and Frameworks for Machine Learning and Deep Learning
This article gives an introduction to Intel’s optimized machine learning and deep learning tools and frameworks.

Improving the Performance of Principal Component Analysis with Intel® Data Analytics Acceleration Library (Intel® DAAL)
This article discusses an unsupervised machine-learning algorithm called principal component analysis (PCA) that can be used to simplify the data.

Accelerating Deep Learning and Machine Learning with Intel Libraries
Accelerating Deep Learning and Machine Learning with Intel Libraries.

Introducing DNN primitives in Intel® Math Kernel Library (Intel® MKL)
Deep Neural Networks (DNNs) are on the cutting edge of the Machine Learning domain. These algorithms received wide industry adoption in the late 1990s and were initially applied to tasks such as handwriting recognition on bank checks.

Improving Support Vector Machine with Intel® Data Analytics Acceleration Library
Improving the Performance of Support Vector Machine with Intel® Data Analytics Acceleration Library Introduction.

Using Intel® Data Analytics Acceleration Library (Intel® DAAL) on Matlab*
Intel® Data Analytics Acceleration Library is a high performance library, which provides a rich set of algorithms, ranging from the ranging from the most basic descriptive statistics for datasets to more advanced data mining and machine learning algorithms.

Using Intel® Data Analytics Acceleration Library to Improve the Performance of Naïve Bayes Algorithm in Python*
This article discusses machine learning and describes a machine learning method/algorithm called Naïve Bayes.

Intel® DAAL
Kent Moffat, Senior Product Manager at Intel, discusses Intel® Data Analytics Acceleration Library (Intel® DAAL) and Intel® Math Kernel Library (Intel® MKL) and how to get started.

Faster Machine Learning and Data Analytics Using Intel® Performance Libraries
Develop software that transforms data to decision-making sooner with Intel Data Analytics Acceleration Library (Intel DAAL) and Intel Math Kernel Library (Intel MKL) 2017.


Remove Python* Performance Barriers for Machine Learning
This webinar highlights significant performance speed-ups achieved by implementing multiple Intel tools and techniques for high-performance Python*.

Getting Started with Intel Software Optimization for Theano* and Intel® Distribution for Python*
Theano* is a Python* library developed at the LISA lab to define, optimize, and evaluate mathematical expressions, including the ones with multi-dimensional arrays (numpy.ndarray).

How to Install the Python* Version of Intel® Data Analytics Acceleration Library (Intel® DAAL)
Intel Data Analytics Acceleration Library (Intel DAAL) is a software solution that offers building blocks covering all the stages of data analytics, from preprocessing to decision making.

Using Intel® Data Analytics Acceleration Library to Improve the Performance of Naïve Bayes Algorithm in Python*
This article discusses machine learning and describes a machine learning method/algorithm called Naïve Bayes.

Intel Distribution for Python*
Intel Distribution for Python* gives ready access to tools and techniques for high performance to supercharge all your Python applications on modern Intel® platforms.


The Evil within the Comparison Functions

$
0
0

Perhaps, readers remember my article titled "Last line effect". It describes a pattern I've once noticed: in most cases programmers make an error in the last line of similar text blocks. Now I want to tell you about a new interesting observation. It turns out that programmers tend to make mistakes in functions comparing two objects. This statement looks implausible; however, I'll show you a great number of examples of errors that may be shocking to a reader. So, here is a new research, it will be quite amusing and scary.

Problematics

Here is my statement: programmers quite often make mistakes in rather simple functions that are meant to compare two objects. This claim is based on the experience of our team in checking a large number of open source projects in C, C++ and C#.

The functions we are going to consider here are IsEqual, Equals, Compare, AreEqual and so on or overloaded operators as ==, !=.

I noticed that when writing articles, very often I come across errors related to the comparison functions. I decided to explore this question in detail and examined the base of errors we found. I did a search of functions throughout the base containing words Cmp, Equal, Compare and such. The result was very impressive and shocking.

In fact this story is similar to the one we had when writing the article "Last line effect". Similarly, I noticed an anomaly and decided to explore it more carefully. Unfortunately, unlike the aforementioned article, I don't know how to bring statistics here and which figures to provide. Perhaps, later I'll come up with a solution with the statistics. At this point I am guided by intuition and can only share my feelings. They see that there are a lot of errors in the comparison functions and I am sure, you will get the same feeling when you see that huge amount of truly impressive examples.

Psychology

For a moment let's go back to the article "Last line effect". By the way, if you haven't read it, I suggest taking a break and looking at it. There is a more detailed analysis of this topic: "The last line effect explained"

In general, we can conclude that the cause of the errors in the last lined is related to the fact that the developer has already mentally moved to the new lines/tasks instead of focusing on the completion of the current fragment. As a result - when writing similar blocks of text, there is a higher probability that a programmer will make an error in the last one.

I believe that in the case of writing a comparison function, a developer in general often don't focus on it, considering it to be too trivial. In other words, he writes the code automatically, without thinking over it. Otherwise, it is not clear how one can make an error like this:

bool IsLuidsEqual(LUID luid1, LUID luid2)
{
  return (luid1.LowPart == luid2.LowPart) &&
         (luid2.HighPart == luid2.HighPart);
}

PVS-Studio analyzer detected this error in the code of RunAsAdmin Explorer Shim (C++) project: V501 There are identical sub-expressions to the left and to the right of the '==' operator: luid2.HighPart == luid2.HighPart RAACommon raacommonfuncs.cpp 1511

A typo. In the second line it should be: luid1.HighPart == luid2.HighPart.

The code is very simple. Apparently, the simplicity of code spoils everything. A programmer immediately thinks of the task to write such a function as standard and uninteresting. He instantly thinks of the way to write the function and he has just to implement the code. This is a routine, but unfortunately an inevitable process to start writing more important, complex and interesting code. He is already thinking about the new task... and as a result - makes an error.

In addition, programmers rarely write unit tests for such functions. Again the simplicity of these functions prevents from it. It seems that it would be too much to test them, as these functions are simple and repetitive. A person has written hundreds of such functions in his life, can he make an error in another function? Yes, he can and he does.

I would also like to note that we aren't talking about code of students who are just learning to program. We are talking about bugs in the code of such projects as GCC, Qt, GDB, LibreOffice, Unreal Engine, CryEngine 4 V Chromium, MongoDB, Oracle VM Virtual Box, FreeBSD, WinMerge, the CoreCLR, MySQL, Mono, CoreFX, Roslyn, MSBuild, etc. It's all very serious.

We are going to have a look at so many diverse examples that it would be scary to sleep at night.

Erroneous Patterns in Comparison Functions

All errors in comparison functions will be divided into several patterns. In the article we'll be talking about errors in projects in C, C++ and C#, but it makes no sense to separate these languages, as most of the patterns are similar for different languages.

Pattern: A < B, B > A

Very often in the comparison functions there is a need to make such checks:

  • A < B
  • A > B

Sometimes programmers think that is more elegant to use the same operator <, but to switch the variables.

  • A < B
  • B < A

However, due to the inattentiveness, we get such checks:

  • A < B
  • B > A

In fact, one and the same comparison is done twice here. Perhaps, it's not clear what it is about here, but we'll get to the practical examples and it'll all become clearer.

string _server;
....
bool operator<( const ServerAndQuery& other ) const {
  if ( ! _orderObject.isEmpty() )
    return _orderObject.woCompare( other._orderObject ) < 0;

  if ( _server < other._server )
    return true;
  if ( other._server > _server )
    return false;
  return _extra.woCompare( other._extra ) < 0;
}

PVS-Studio analyzer detected this error in the code of MongoDB (C++): V581 The conditional expressions of the 'if' operators situated alongside each other are identical. Check lines: 44, 46. parallel.h 46

This condition:

if ( other._server > _server )

Will always be false, as the same check was done two lines before. Correct code variant:

if ( _server < other._server )
  return true;
if ( other._server < _server )
  return false;

This error was detected in the code of Chromium project (C++):

enum ContentSettingsType;
struct EntryMapKey {
  ContentSettingsType content_type;
  ...
};

bool OriginIdentifierValueMap::EntryMapKey::operator<(
    const OriginIdentifierValueMap::EntryMapKey& other) const {
  if (content_type < other.content_type)
    return true;
  else if (other.content_type > content_type)
    return false;
  return (resource_identifier < other.resource_identifier);
}

PVS-Studio warning: V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 61, 63. browser content_settings_origin_identifier_value_map.cc 61

That was a C++ example, now it's C# turn. The next error was found in the code of IronPython and IronRuby (C#).

public static int Compare(SourceLocation left,
                          SourceLocation right) {
  if (left < right) return -1;
  if (right > left) return 1;
  return 0;
}

PVS-Studio warning (C#): V3021 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains method return. This means that the second 'if' statement is senseless. SourceLocation.cs 156

I think there is no need in explanation.

Note. For C# there was just one example of an error, but for C++ - two. In general, there will be less bugs in the C# code, than for C/C++. But I do not recommend rushing to the conclusion that C# is much safer. The thing is that PVS-Studio analyzer has only recently learned to check C# code relatively recently, and we have just checked less projects written in C#, than in C and C++.

Pattern: a Member of the Class is Compared with itself

The comparison functions usually consist of successive comparisons of structure/class members. This code tends to be more erronreous, when the member of the class starts being compared with itself. I can specify two subtypes of errors.

In the first case, a programmer forgets to specify the name of the object and writes in the following way:

return m_x == foo.m_x &&
       m_y == m_y &&            // <=
       m_z == foo.m_z;
In the second case, the same name of the object is written.
return zzz.m_x == foo.m_x &&
       zzz.m_y == zzz.m_y &&    // <=
       zzz.m_z == foo.m_z;

Let's take a closer look at practical examples of this pattern. Pay attention that incorrect comparison often occurs in the last block of similar code blocks, which reminds us of the "last line effect" again.

The error is found in the code of Unreal Engine 4 (C++) project:

bool
Compare(const FPooledRenderTargetDesc& rhs, bool bExact) const
{
  ....
  return Extent == rhs.Extent&& Depth == rhs.Depth&& bIsArray == rhs.bIsArray&& ArraySize == rhs.ArraySize&& NumMips == rhs.NumMips&& NumSamples == rhs.NumSamples&& Format == rhs.Format&& LhsFlags == RhsFlags&& TargetableFlags == rhs.TargetableFlags&& bForceSeparateTargetAndShaderResource ==
         rhs.bForceSeparateTargetAndShaderResource&& ClearValue == rhs.ClearValue&& AutoWritable == AutoWritable;           // <=
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: AutoWritable == AutoWritable rendererinterface.h 180

The code of Samba (C) project:

static int compare_procids(const void *p1, const void *p2)
{
  const struct server_id *i1 = (struct server_id *)p1;
  const struct server_id *i2 = (struct server_id *)p2;

  if (i1->pid < i2->pid) return -1;
  if (i2->pid > i2->pid) return 1;
  return 0;
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '>' operator: i2->pid > i2->pid brlock.c 1901

The code of MongoDB (C++) project:

bool operator==(const MemberCfg& r) const {
  ....
  return _id==r._id && votes == r.votes &&
         h == r.h && priority == r.priority &&
         arbiterOnly == r.arbiterOnly &&
         slaveDelay == r.slaveDelay &&
         hidden == r.hidden &&
         buildIndexes == buildIndexes;        // <=
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: buildIndexes == buildIndexes rs_config.h 101

The code of Geant4 Software (C++) project:

inline G4bool G4FermiIntegerPartition::
operator==(const G4FermiIntegerPartition& right)
{
  return (total == right.total &&
          enableNull == enableNull &&          // <=
          partition == right.partition);
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: enableNull == enableNull G4hadronic_deex_fermi_breakup g4fermiintegerpartition.icc 58

The code of LibreOffice (C++) project:

class SvgGradientEntry
{
  ....
  bool operator==(const SvgGradientEntry& rCompare) const
  {
    return (getOffset() == rCompare.getOffset()&& getColor() == getColor()            // <=&& getOpacity() == getOpacity());      // <=
  }
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: getColor() == getColor() svggradientprimitive2d.hxx 61

The code of Chromium (C++) project:

bool FileIOTest::MatchesResult(const TestStep& a,
                               const TestStep& b) {
  ....
  return (a.data_size == a.data_size &&             // <=
          std::equal(a.data, a.data + a.data_size, b.data));
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: a.data_size == a.data_size cdm_file_io_test.cc 367

The code of FreeCAD (C++) project:

bool FaceTypedBSpline::isEqual(const TopoDS_Face &faceOne,
                               const TopoDS_Face &faceTwo) const
{
  ....
  if (surfaceOne->IsURational() !=
      surfaceTwo->IsURational())
    return false;
  if (surfaceTwo->IsVRational() !=         // <=
      surfaceTwo->IsVRational())           // <=
    return false;
  if (surfaceOne->IsUPeriodic() !=
      surfaceTwo->IsUPeriodic())
    return false;
  if (surfaceOne->IsVPeriodic() !=
      surfaceTwo->IsVPeriodic())
    return false;
  if (surfaceOne->IsUClosed() !=
      surfaceTwo->IsUClosed())
    return false;
  if (surfaceOne->IsVClosed() !=
      surfaceTwo->IsVClosed())
    return false;
  if (surfaceOne->UDegree() !=
      surfaceTwo->UDegree())
    return false;
  if (surfaceOne->VDegree() !=
      surfaceTwo->VDegree())
    return false;
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions 'surfaceTwo->IsVRational()' to the left and to the right of the '!=' operator. modelrefine.cpp 780

The code of Serious Engine (C++) project:

class CTexParams {
public:

  inline BOOL IsEqual( CTexParams tp) {
    return tp_iFilter     == tp.tp_iFilter &&
           tp_iAnisotropy == tp_iAnisotropy &&             // <=
           tp_eWrapU      == tp.tp_eWrapU &&
           tp_eWrapV      == tp.tp_eWrapV; };
  ....
};

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: tp_iAnisotropy == tp_iAnisotropy gfx_wrapper.h 180

The code of Qt (C++) project:

inline bool qCompare(QImage const &t1, QImage const &t2, ....)
{
  ....
  if (t1.width() != t2.width() || t2.height() != t2.height()) {
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '!=' operator: t2.height() != t2.height() qtest_gui.h 101

The code of FreeBSD (C) project:

static int
compare_sh(const void *_a, const void *_b)
{
  const struct ipfw_sopt_handler *a, *b;

  a = (const struct ipfw_sopt_handler *)_a;
  b = (const struct ipfw_sopt_handler *)_b;
  ....
  if ((uintptr_t)a->handler < (uintptr_t)b->handler)
    return (-1);
  else if ((uintptr_t)b->handler > (uintptr_t)b->handler) // <=
    return (1);

  return (0);
}

PVS-Studio warning: V501 There are identical sub-expressions '(uintptr_t) b->handler' to the left and to the right of the '>' operator. ip_fw_sockopt.c 2893

The code of Mono (C#) project:

static bool AreEqual (VisualStyleElement value1,
                      VisualStyleElement value2)
{
  return
    value1.ClassName == value1.ClassName && // <=
    value1.Part == value2.Part &&
    value1.State == value2.State;
}

PVS-Studio warning: V3001 There are identical sub-expressions 'value1.ClassName' to the left and to the right of the '==' operator. ThemeVisualStyles.cs 2141

The code of Mono (C#) project:

public int ExactInference (TypeSpec u, TypeSpec v)
{
  ....
  var ac_u = (ArrayContainer) u;
  var ac_v = (ArrayContainer) v;
  ....
  var ga_u = u.TypeArguments;
  var ga_v = v.TypeArguments;
  ....
  if (u.TypeArguments.Length != u.TypeArguments.Length) // <=
    return 0;

  ....
}

PVS-Studio warning: V3001 There are identical sub-expressions 'u.TypeArguments.Length' to the left and to the right of the '!=' operator. generic.cs 3135

The code of MonoDevelop (C#) project:

Accessibility DeclaredAccessibility { get; }
bool IsStatic { get; }

private bool MembersMatch(ISymbol member1, ISymbol member2)
{
  if (member1.Kind != member2.Kind)
  {
    return false;
  }

  if (member1.DeclaredAccessibility !=          // <=1
      member1.DeclaredAccessibility             // <=1
   || member1.IsStatic != member1.IsStatic)     // <=2
  {
    return false;
  }

  if (member1.ExplicitInterfaceImplementations().Any() ||
      member2.ExplicitInterfaceImplementations().Any())
  {
    return false;
  }

  return SignatureComparer
    .HaveSameSignatureAndConstraintsAndReturnTypeAndAccessors(
       member1, member2, this.IsCaseSensitive);
}

PVS-Studio warning: V3001 There are identical sub-expressions 'member1.IsStatic' to the left and to the right of the '!=' operator. CSharpBinding AbstractImplementInterfaceService.CodeAction.cs 545

The code of Haiku (C++) project:

int __CORTEX_NAMESPACE__ compareTypeAndID(....)
{
  int retValue = 0;
  ....
  if (lJack && rJack)
  {
    if (lJack->m_jackType < lJack->m_jackType)           // <=
    {
      return -1;
    }
    if (lJack->m_jackType == lJack->m_jackType)          // <=
    {
      if (lJack->m_index < rJack->m_index)
      {
        return -1;
      }
      else
      {
        return 1;
      }
    }
    else if (lJack->m_jackType > rJack->m_jackType)
    {
      retValue = 1;
    }
  }
  return retValue;
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '<' operator: lJack->m_jackType < lJack->m_jackType MediaJack.cpp 783

Just below there is exactly the same error. As I understand, in both cases a programmer forgot to replace lJack with rJack.

The code of CryEngine V (C++) project:

bool
CompareRotation(const Quat& q1, const Quat& q2, float epsilon)
{
  return (fabs_tpl(q1.v.x - q2.v.x) <= epsilon)&& (fabs_tpl(q1.v.y - q2.v.y) <= epsilon)&& (fabs_tpl(q2.v.z - q2.v.z) <= epsilon)     // <=&& (fabs_tpl(q1.w - q2.w) <= epsilon);
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '-' operator: q2.v.z - q2.v.z entitynode.cpp 93

Pattern: Evaluating the Size of a Pointer Instead of the Size of the Structure/Class

This type of error occurs in programs written in C and C++ and is caused by incorrect use of the sizeof operator. The error in evaluating not the size of the object, but the size of the pointer. Example:

T *a = foo1();
T *b = foo2();
x = memcmp(a, b, sizeof(a));

Instead of the size of the T structure, a size of the pointer gets evaluated. The size of the pointer depends on the used data model, but usually it is 4 or 8. As a result, more or less bites in the memory get compared than take the structure.

Correct variant of the code:

x = memcmp(a, b, sizeof(T));

or

x = memcmp(a, b, sizeof(*a));

Now let's move on to the practical part. Here is how such a bug looks in the code of CryEngine V (C++) code:

bool
operator==(const SComputePipelineStateDescription& other) const
{
  return 0 == memcmp(this, &other, sizeof(this));
}

PVS-Studio warning: V579 The memcmp function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. graphicspipelinestateset.h 58

The code of Unreal Engine 4 project (C++):

bool FRecastQueryFilter::IsEqual(
  const INavigationQueryFilterInterface* Other) const
{
  // @NOTE: not type safe, should be changed when
  // another filter type is introduced
  return FMemory::Memcmp(this, Other, sizeof(this)) == 0;

}

PVS-Studio warning: V579 The Memcmp function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. pimplrecastnavmesh.cpp 172

Pattern: Repetitive Arguments of Cmp(A, A) Type

Comparison functions usually call other comparison functions. At the same time one of the possible errors is that the reference/pointer is passed to the same object twice. Example:

x = memcmp(A, A, sizeof(T));

Here the object A will be compared with itself, which, is of course, has no sense.

We'll start with an error, found in the debugger GDB (C):

static int
psymbol_compare (const void *addr1, const void *addr2,
                 int length)
{
  struct partial_symbol *sym1 = (struct partial_symbol *) addr1;
  struct partial_symbol *sym2 = (struct partial_symbol *) addr2;

  return (memcmp (&sym1->ginfo.value, &sym1->ginfo.value,    // <=
                  sizeof (sym1->ginfo.value)) == 0&& sym1->ginfo.language == sym2->ginfo.language&& PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2)&& PSYMBOL_CLASS (sym1) == PSYMBOL_CLASS (sym2)&& sym1->ginfo.name == sym2->ginfo.name);
}

PVS-Studio warning: V549 The first argument of 'memcmp' function is equal to the second argument. psymtab.c 1580

The code of CryEngineSDK project (C++):

inline bool operator != (const SEfResTexture &m) const
{
  if (stricmp(m_Name.c_str(), m_Name.c_str()) != 0 ||   // <=
      m_TexFlags != m.m_TexFlags ||
      m_bUTile != m.m_bUTile ||
      m_bVTile != m.m_bVTile ||
      m_Filter != m.m_Filter ||
      m_Ext != m.m_Ext ||
      m_Sampler != m.m_Sampler)
    return true;
  return false;
}

PVS-Studio warning: V549 The first argument of 'stricmp' function is equal to the second argument. ishader.h 2089

The code of PascalABC.NET (C#):

private List<string> enum_consts = new List<string>();
public override bool IsEqual(SymScope ts)
{
  EnumScope es = ts as EnumScope;
  if (es == null) return false;
  if (enum_consts.Count != es.enum_consts.Count) return false;
  for (int i = 0; i < es.enum_consts.Count; i++)
    if (string.Compare(enum_consts[i],
                       this.enum_consts[i], true) != 0)
      return false;
  return true;
}

PVS-Studio warning: V3038 The 'enum_consts[i]' argument was passed to 'Compare' method several times. It is possible that other argument should be passed instead. CodeCompletion SymTable.cs 2206

I'll give some explanation here. The error in the factual arguments of the Compare function:

string.Compare(enum_consts[i], this.enum_consts[i], true)

The thing is that enum_consts[i] and this.enum_consts[i are the same things. As I understand, a correct call should be like this:

string.Compare(es.enum_consts[i], this.enum_consts[i], true)

or

string.Compare(enum_consts[i], es.enum_consts[i], true)

Pattern: Repetitive Checks A==B && A==B

Quite a common error in programming is when the same check is done twice. Example:

return A == B &&
       C == D &&   // <=
       C == D &&   // <=
       E == F;

Two variants are possible in this case. The first is quite harmless: one comparison is redundant and can be simply removed. The second is worse: some other variables were to be compared, but a programmer made a typo.

In any case, such code deserves close attention. Let me scare you a little more, and show that this error can be found even in the code of GCC compiler (C):

static bool
dw_val_equal_p (dw_val_node *a, dw_val_node *b)
{
  ....
  case dw_val_class_vms_delta:
    return (!strcmp (a->v.val_vms_delta.lbl1,
                     b->v.val_vms_delta.lbl1)&& !strcmp (a->v.val_vms_delta.lbl1,
                        b->v.val_vms_delta.lbl1));
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions '!strcmp(a->v.val_vms_delta.lbl1, b->v.val_vms_delta.lbl1)' to the left and to the right of the '&&' operator. dwarf2out.c 1428

The function strcmp is called twice with the same set of arguments.

The code of Unreal Engine 4 project (C++):

FORCEINLINE
bool operator==(const FShapedGlyphEntryKey& Other) const
{
  return FontFace == Other.FontFace&& GlyphIndex == Other.GlyphIndex   // <=&& FontSize == Other.FontSize&& FontScale == Other.FontScale&& GlyphIndex == Other.GlyphIndex;  // <=
}

PVS-Studio warning: V501 There are identical sub-expressions 'GlyphIndex == Other.GlyphIndex' to the left and to the right of the '&&' operator. fontcache.h 139

The code of Serious Engine project (C++):

inline BOOL CValuesForPrimitive::operator==(....)
{
  return (
 (....) &&
 (vfp_ptPrimitiveType == vfpToCompare.vfp_ptPrimitiveType) &&
 ....
 (vfp_ptPrimitiveType == vfpToCompare.vfp_ptPrimitiveType) &&
 ....
);

PVS-Studio warning: V501 There are identical sub-expressions '(vfp_ptPrimitiveType == vfpToCompare.vfp_ptPrimitiveType)' to the left and to the right of the '&&' operator. worldeditor.h 580

The code of Oracle VM Virtual Box project (C++):

typedef struct SCMDIFFSTATE
{
  ....
  bool  fIgnoreTrailingWhite;
  bool  fIgnoreLeadingWhite;
  ....
} SCMDIFFSTATE;
/* Pointer to a diff state. */

typedef SCMDIFFSTATE *PSCMDIFFSTATE;

/* Compare two lines */
DECLINLINE(bool) scmDiffCompare(PSCMDIFFSTATE pState, ....)
{
  ....
  if (pState->fIgnoreTrailingWhite    // <=
   || pState->fIgnoreTrailingWhite)   // <=
    return scmDiffCompareSlow(....);
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions 'pState->fIgnoreTrailingWhite' to the left and to the right of the '||' operator. scmdiff.cpp 238

Pattern: Incorrect Use of the Value, Returned by memcmp Function

The memcmp function returns the following values of int type:

  • < 0 - buf1 less than buf2;
  • 0 - buf1 identical to buf2;
  • > 0 - buf1 greater than buf2;

Please note that '>0' can be any number, not only 1. These numbers can be: 2, 3, 100, 256, 1024, 5555, 65536 and so on. This means that this result cannot be placed to a variable of the char and short type. The high bits can be lost, which might violate the logic of program execution.

Also this means that the result cannot be compared with constants 1 or -1. In other words, it is wrong to write this:

if (memcmp(a, b, sizeof(T)) == 1)
if (memcmp(x, y, sizeof(T)) == -1)

Correct comparisons:

if (memcmp(a, b, sizeof(T)) > 0)
if (memcmp(a, b, sizeof(T)) < 0)

The danger of this code is that it may successfully work for a long time. The errors may start showing up when moving to a new platform or with the change of the compiler version.

The code of ReactOS project (C++):

HRESULT WINAPI CRecycleBin::CompareIDs(....)
{
  ....
  return MAKE_HRESULT(SEVERITY_SUCCESS, 0,
   (unsigned short)memcmp(pidl1->mkid.abID,
                          pidl2->mkid.abID,
                          pidl1->mkid.cb));
}

PVS-Studio warning: V642 Saving the 'memcmp' function result inside the 'unsigned short' type variable is inappropriate. The significant bits could be lost breaking the program's logic. recyclebin.cpp 542

The code of Firebird project (C++):

SSHORT TextType::compare(ULONG len1, const UCHAR* str1,
ULONG len2, const UCHAR* str2)
{
  ....
  SSHORT cmp = memcmp(str1, str2, MIN(len1, len2));

  if (cmp == 0)
    cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0));
  return cmp;
}

PVS-Studio warning: V642 Saving the 'memcmp' function result inside the 'short' type variable is inappropriate. The significant bits could be lost breaking the program's logic. texttype.cpp 338

The code of CoreCLR project (C++):

bool operator( )(const GUID& _Key1, const GUID& _Key2) const
  { return memcmp(&_Key1, &_Key2, sizeof(GUID)) == -1; }

PVS-Studio warning: V698 Expression 'memcmp(....) == -1' is incorrect. This function can return not only the value '-1', but any negative value. Consider using 'memcmp(....) < 0' instead. sos util.cpp 142

The code of OpenToonz project (C++):

bool TFilePath::operator<(const TFilePath &fp) const
{
  ....
  char differ;
  differ = _wcsicmp(iName.c_str(), jName.c_str());
  if (differ != 0)
    return differ < 0 ? true : false;
  ....
}

PVS-Studio warning: V642 Saving the '_wcsicmp' function result inside the 'char' type variable is inappropriate. The significant bits could be lost, breaking the program's logic. tfilepath.cpp 328

Pattern: Incorrect Check of Null References

This error pattern is typical for C# programs. Sometimes in the comparison functions programmers write the type casting with the help of the as operator. The error is that inadvertently a programmer verifies against null not the new reference, but the original one. Let's take a look at a synthetic example:

ChildT foo = obj as ChildT;
if (obj == null)
  return false;
if (foo.zzz()) {}

The check if (obj == null) protects from the situation, if the obj variable contains a null reference. However, there is no protection from the case if it turns out that the as operator returns a null reference. The correct code should be like this:

ChildT foo = obj as ChildT;
if (foo == null)
  return false;
if (foo.zzz()) {}

Typically, this error occurs due to negligence of the programmer. Similar bugs are possible in the programs in C and C++, but I haven't found such a case in our error base.

The code of MonoDevelop project (C#):

public override bool Equals (object o)
{
  SolutionItemReference sr = o as SolutionItemReference;
  if (o == null)
    return false;
  return (path == sr.path) && (id == sr.id);
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'o', 'sr'. MonoDevelop.Core SolutionItemReference.cs 81

The code of CoreFX (C#):

public override bool Equals(object comparand)
{
  CredentialHostKey comparedCredentialKey =
                                  comparand as CredentialHostKey;

  if (comparand == null)
  {
    // This covers also the compared == null case
    return false;
  }

  bool equals = string.Equals(AuthenticationType,
        comparedCredentialKey.AuthenticationType, ....
  ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'comparand', 'comparedCredentialKey'. CredentialCache.cs 4007

The code of Roslyn project (C#):

public override bool Equals(object obj)
{
  var d = obj as DiagnosticDescription;

  if (obj == null)
    return false;

  if (!_code.Equals(d._code))
    return false;
  ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'd'. DiagnosticDescription.cs 201

The code of Roslyn (C#):

protected override bool AreEqual(object other)
{
  var otherResourceString = other as LocalizableResourceString;
  return
    other != null &&
    _nameOfLocalizableResource ==
      otherResourceString._nameOfLocalizableResource &&
    _resourceManager == otherResourceString._resourceManager &&
    _resourceSource == otherResourceString._resourceSource &&
    ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'other', 'otherResourceString'. LocalizableResourceString.cs 121

The code of MSBuild project (C#):

public override bool Equals(object obj)
{
   AssemblyNameExtension name = obj as AssemblyNameExtension;
   if (obj == null)  // <=
   {
     return false;
   }
   ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'name'. AssemblyRemapping.cs 64

The code of Mono project (C#):

public override bool Equals (object o)
{
  UrlMembershipCondition umc = (o as UrlMembershipCondition);
  if (o == null)                                      // <=
    return false;

  ....

  return (String.Compare (u, 0, umc.Url, ....) == 0); // <=
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'o', 'umc'. UrlMembershipCondition.cs 111

The code of Media Portal 2 project (C#):

public override bool Equals(object obj)
{
  EpisodeInfo other = obj as EpisodeInfo;
  if (obj == null) return false;
  if (TvdbId > 0 && other.TvdbId > 0)
    return TvdbId == other.TvdbId;
  ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'other'. EpisodeInfo.cs 560

The code of NASA World Wind project (C#):

public int CompareTo(object obj)
{
  RenderableObject robj = obj as RenderableObject;
  if(obj == null)                                 // <=
    return 1;
  return this.m_renderPriority.CompareTo(robj.RenderPriority);
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'robj'. RenderableObject.cs 199

Pattern: Incorrect Loops

In some functions, collections of items are compared. Of course, different variant of the loops are used for its comparison. If a programmer writes the code inattentively, it's easy to mix something up, as it is with the comparison functions. Let's look at a few of these situations.

The code of Trans-Proteomic Pipeline (C++):

bool Peptide::operator==(Peptide& p) {
  ....
  for (i = 0, j = 0;
       i < this->stripped.length(), j < p.stripped.length();
       i++, j++) {
  ....
}

PVS-Studio warning: V521 Such expressions using the ',' operator are dangerous. Make sure the expression is correct. tpplib peptide.cpp 191

Note that the comma operator is used in the condition. The code is clearly incorrect, because the condition, written to the left of the coma is ignored. That is, the condition on the left is evaluated, but its result is not used in any way.

The code of Qt project (C++):

bool equals( class1* val1, class2* val2 ) const
{
  ...
  size_t size = val1->size();
  ...
  while ( --size >= 0 ){
    if ( !comp(*itr1,*itr2) )
      return false;
    itr1++;
    itr2++;
  }
  ...
}

PVS-Studio warning: V547 Expression '-- size >= 0' is always true. Unsigned type value is always >= 0. QtCLucene arrays.h 154

The code of CLucene project (C++):

class Arrays
{
  ....
   bool equals( class1* val1, class2* val2 ) const{
     static _comparator comp;
     if ( val1 == val2 )
       return true;
     size_t size = val1->size();
     if ( size != val2->size() )
       return false;
     _itr1 itr1 = val1->begin();
     _itr2 itr2 = val2->begin();
     while ( --size >= 0 ){
       if ( !comp(*itr1,*itr2) )
         return false;
       itr1++;
       itr2++;
     }
   return true;
  }
  ....
}

PVS-Studio warning: V547 Expression '-- size >= 0' is always true. Unsigned type value is always >= 0. arrays.h 154

The code of Mono project (C#):

public override bool Equals (object obj)
{
  ....
  for (int i=0; i < list.Count; i++) {
    bool found = false;
    for (int j=0; i < ps.list.Count; j++) {     // <=
      if (list [i].Equals (ps.list [j])) {
        found = true;
        break;
      }
    }
    if (!found)
      return false;
  }
  return true;
}

PVS-Studio warning: V3015 It is likely that a wrong variable is being compared inside the 'for' operator. Consider reviewing 'i' corlib-net_4_x PermissionSet.cs 607

Apparently, there is a typo here, and the variable j instead of i should be used in the nested loop:

for (int j=0; j < ps.list.Count; j++)

Pattern: A = getA(), B = GetA()

Quite often in the comparison functions a programmer has to write code of this kind:

if (GetA().x == GetB().x && GetA().y == GetB().y)

Intermediate variables are used to reduce the size of the conditions or for optimization:

Type A = GetA();
Type B = GetB();
if (A.x == B.x && A.y == B.y)

But inadvertently, a person sometimes makes a mistake and initializes temporary variables with the same value:

Type A = GetA();
Type B = GetA();

Now let's take a look at these errors in the code of real applications.

The code of LibreOffice project (C++):

bool CmpAttr(
  const SfxPoolItem& rItem1, const SfxPoolItem& rItem2)
{
  ....
  bool bNumOffsetEqual = false;
  ::boost::optional<sal_uInt16> oNumOffset1 =
        static_cast<const SwFmtPageDesc&>(rItem1).GetNumOffset();
  ::boost::optional<sal_uInt16> oNumOffset2 =
        static_cast<const SwFmtPageDesc&>(rItem1).GetNumOffset();

  if (!oNumOffset1 && !oNumOffset2)
  {
    bNumOffsetEqual = true;
  }
  else if (oNumOffset1 && oNumOffset2)
  {
    bNumOffsetEqual = oNumOffset1.get() == oNumOffset2.get();
  }
  else
  {
    bNumOffsetEqual = false;
  }
  ....
}

PVS-Studio warning: V656 Variables 'oNumOffset1', 'oNumOffset2' are initialized through the call to the same function. It's probably an error or un-optimized code. Check lines: 68, 69. findattr.cxx 69

The code of Qt project (C++):

AtomicComparator::ComparisonResult
IntegerComparator::compare(const Item &o1,
                           const AtomicComparator::Operator,
                           const Item &o2) const
{
  const Numeric *const num1 = o1.as<Numeric>();
  const Numeric *const num2 = o1.as<Numeric>();

  if(num1->isSigned() || num2->isSigned())
  ....
}

PVS-Studio warning: V656 Variables 'num1', 'num2' are initialized through the call to the same function. It's probably an error or un-optimized code. Consider inspecting the 'o1.as < Numeric > ()' expression. Check lines: 220, 221. qatomiccomparators.cpp 221

Pattern: Sloppy Copying of the Code

A large amount of errors, cited previously can be called the consequences of sloppy Copy-Paste. They fell under some categories of the erroneous pattern and I decided that it would be logical to describe them in corresponding sections. However, I have several errors that have clearly appeared because of sloppy code copying, but I have no idea how to classify them. That's why I collected these errors here.

The code of CoreCLR project (C++):

int __cdecl Compiler::RefCntCmp(const void* op1, const void* op2)
{
  ....
  if (weight1)
  {
    ....
    if (varTypeIsGC(dsc1->TypeGet()))
    {
      weight1 += BB_UNITY_WEIGHT / 2;
    }
    if (dsc1->lvRegister)
    {
      weight1 += BB_UNITY_WEIGHT / 2;
    }
  }

  if (weight1)
  {
    ....
    if (varTypeIsGC(dsc2->TypeGet()))
    {
      weight1 += BB_UNITY_WEIGHT / 2;       // <=
    }
    if (dsc2->lvRegister)
    {
      weight2 += BB_UNITY_WEIGHT / 2;
    }
  }
  ....
}

PVS-Studio warning: V778 Two similar code fragments were found. Perhaps, this is a typo and 'weight2' variable should be used instead of 'weight1'. clrjit lclvars.cpp 2702

The function was long that's why it is shortened for the article. If we examine the code of the function, we'll see that a part of the code was copied, but in one fragment a programmer forgot to replace the variable weight1 with weight2.

The code of WPF samples by Microsoft project (C#):

public int Compare(GlyphRun a, GlyphRun b)
{
  ....
  if (aPoint.Y > bPoint.Y)      // <=
  {
    return -1;
  }
  else if (aPoint.Y > bPoint.Y) // <=
  {
    result = 1;
  }
  else if (aPoint.X < bPoint.X)
  {
    result = -1;
  }
  else if (aPoint.X > bPoint.X)
  {
    result = 1;
  }
  ....
}

PVS-Studio warning: V3003 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 418, 422. txtserializerwriter.cs 418

The code of PascalABC.NET project (C#):

public void CompareInternal(....)
{
  ....
  else if (left is int64_const)
    CompareInternal(left as int64_const, right as int64_const);
  ....
  else if (left is int64_const)
    CompareInternal(left as int64_const, right as int64_const);
  ....
}

PVS-Studio warning: V3003 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 597, 631. ParserTools SyntaxTreeComparer.cs 597

The code of SharpDevelop project (C#):

public int Compare(SharpTreeNode x, SharpTreeNode y)
{
  ....
  if (typeNameComparison == 0) {
    if (x.Text.ToString().Length < y.Text.ToString().Length)
      return -1;
    if (x.Text.ToString().Length < y.Text.ToString().Length)
      return 1;
  }
  ....
}

PVS-Studio warning: V3021 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains method return. This means that the second 'if' statement is senseless NamespaceTreeNode.cs 87

The code of Coin3D (C++):

int
SbProfilingData::operator == (const SbProfilingData & rhs) const
{
  if (this->actionType != rhs.actionType) return FALSE;
  if (this->actionStartTime != rhs.actionStopTime) return FALSE;
  if (this->actionStartTime != rhs.actionStopTime) return FALSE;
  ....
}

PVS-Studio warning: V649 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains function return. This means that the second 'if' statement is senseless. Check lines: 1205, 1206. sbprofilingdata.cpp 1206

The code of Spring (C++):

bool operator < (const aiFloatKey& o) const
  {return mTime < o.mTime;}
bool operator > (const aiFloatKey& o) const
  {return mTime < o.mTime;}

PVS-Studio warning: V524 It is odd that the body of '>' function is fully equivalent to the body of '<' function. assimp 3dshelper.h 470

And here is the last, particularly interesting code fragment that PVS-Studio analyzer found in MySQL project (C++).

static int rr_cmp(uchar *a,uchar *b)
{
  if (a[0] != b[0])
    return (int) a[0] - (int) b[0];
  if (a[1] != b[1])
    return (int) a[1] - (int) b[1];
  if (a[2] != b[2])
    return (int) a[2] - (int) b[2];
  if (a[3] != b[3])
    return (int) a[3] - (int) b[3];
  if (a[4] != b[4])
    return (int) a[4] - (int) b[4];
  if (a[5] != b[5])
    return (int) a[1] - (int) b[5]; // <=
  if (a[6] != b[6])
    return (int) a[6] - (int) b[6];
  return (int) a[7] - (int) b[7];
}

PVS-Studio warning: V525 The code containing the collection of similar blocks. Check items '0', '1', '2', '3', '4', '1', '6' in lines 680, 682, 684, 689, 691, 693, 695. sql records.cc 680

Most likely, a programmer wrote the first comparison, then the second and got bored. So he copied to the buffer a text block:

if (a[1] != b[1])
  return (int) a[1] - (int) b[1];

A pasted it to the text of the program as many times as he needed. Then he changed indexes, but made a mistake in one place and got an incorrect comparison:

if (a[5] != b[5])
  return (int) a[1] - (int) b[5];

Note. I discuss this error in more detail in my mini-book "The Ultimate Question of Programming, Refactoring, and Everything" (see a chapter "Don't do the compiler's job").

Pattern: Equals Method Incorrectly Processes a Null Reference

In C# the accepted practice is to implement the Equals methods in such a way, so that they correctly process a situation, if a null reference is passed as an argument. Unfortunately, not all the methods are implemented according to this rule.

The code of GitExtensions (C#):

public override bool Equals(object obj)
{
  return GetHashCode() == obj.GetHashCode(); // <=
}

PVS-Studio warning: V3115 Passing 'null' to 'Equals(object obj)' method should not result in 'NullReferenceException'. Git.hub Organization.cs 14

The code of PascalABC.NET project (C#):

public override bool Equals(object obj)
{
  var rhs = obj as ServiceReferenceMapFile;
  return FileName == rhs.FileName;
}

PVS-Studio warning: V3115 Passing 'null' to 'Equals' method should not result in 'NullReferenceException'. ICSharpCode.SharpDevelop ServiceReferenceMapFile.cs 31

Miscellaneous Errors

The code of G3D Content Pak project (C++):

bool Matrix4::operator==(const Matrix4& other) const {
  if (memcmp(this, &other, sizeof(Matrix4) == 0)) {
    return true;
  }
  ...
}

PVS-Studio warning: V575 The 'memcmp' function processes '0' elements. Inspect the 'third' argument. graphics3D matrix4.cpp 269

One closing bracket is put incorrectly. As a result, the amount of bites compared is evaluated by the statement sizeof(Matrix4) == 0. The size of any class is more than 0, which means that the result of the expression is 0. Thus, 0 bites get compared.

Correct variant:

if (memcmp(this, &other, sizeof(Matrix4)) == 0) {

The code of Wolfenstein 3D project (C++):

inline int operator!=( quat_t a, quat_t b )
{
  return ( ( a.x != b.x ) || ( a.y != b.y ) ||
           ( a.z != b.z ) && ( a.w != b.w ) );
}

PVS-Studio warning: V648 Priority of the '&&' operation is higher than that of the '||' operation. math_quaternion.h 167

Apparently, in one fragment the && operator was accidentally written instead of ||.

The code of FlightGear project (C):

static int tokMatch(struct Token* a, struct Token* b)
{
  int i, l = a->strlen;
  if(!a || !b) return 0;
  ....
}

PVS-Studio warning: V595 The 'a' pointer was utilized before it was verified against nullptr. Check lines: 478, 479. codegen.c 478

If we pass NULL as the first argument to the function, we'll get null pointer dereference, although the programmer wanted the function to return 0.

The code of WinMerge project (C++):

int TimeSizeCompare::CompareFiles(int compMethod,
                                  const DIFFITEM &di)
{
  UINT code = DIFFCODE::SAME;
  ...
  if (di.left.size != di.right.size)
  {
    code &= ~DIFFCODE::SAME;
    code = DIFFCODE::DIFF;
  }
  ...
}

PVS-Studio warning: V519 The 'code' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 79, 80. Merge timesizecompare.cpp 80

The code of ReactOS project (C++):

#define IsEqualGUID(rguid1, rguid2) \
  (!memcmp(&(rguid1), &(rguid2), sizeof(GUID)))

static int ctl2_find_guid(....)
{
  MSFT_GuidEntry *guidentry;
  ...
  if (IsEqualGUID(guidentry, guid)) return offset;
  ...
}

PVS-Studio warning: V512 A call of the 'memcmp' function will lead to underflow of the buffer 'guidentry'. oleaut32 typelib2.c 320

A pointer is written here as the first argument. As a result, the address of the pointer gets evaluated, which has no sense.

Correct variant:

if (IsEqualGUID(*guidentry, guid)) return offset;

The code of IronPython and IronRuby project (C#):

public static bool Equals(float x, float y) {
  if (x == y) {
    return !Single.IsNaN(x);
  }
  return x == y;
}

PVS-Studio warning: V3024 An odd precise comparison: x == y. Consider using a comparison with defined precision: Math.Abs(A - B) < Epsilon. FloatOps.cs 1048

It's not clear what is the point of a special check against NaN here. If the condition (x == y) is true, it means that both x and y and different from NaN, because NaN isn't equal to any other value, including itself. It seems that the check against NaN is just not necessary, and the code can be shortened to:

public static bool Equals(float x, float y) {
  return x == y;
}

The code of Mono project (C#):

public bool Equals (CounterSample other)
{
  return
    rawValue         == other.rawValue         &&
    baseValue        == other.counterFrequency &&   // <=
    counterFrequency == other.counterFrequency &&   // <=
    systemFrequency  == other.systemFrequency  &&
    timeStamp        == other.timeStamp        &&
    timeStamp100nSec == other.timeStamp100nSec &&
    counterTimeStamp == other.counterTimeStamp &&
    counterType      == other.counterType;
}

PVS-Studio warning: V3112 An abnormality within similar comparisons. It is possible that a typo is present inside the expression 'baseValue == other.counterFrequency'. System-net_4_x CounterSample.cs 139

How Do these Programs Work at all?

Looking through all the errors, it seems miraculous that all these programs generally work. Indeed, the comparison functions do a very important and responsible task in program.

There are several explanations of why these programs work despite these errors:

  1. In a lot of functions, only a part of the object is compared incorrectly. The partial comparison is enough for most of the tasks in this program.
  2. There are no situations (yet) when the function works incorrectly. For example, this applies to the functions that aren't protected from null pointers or those, where the result of the memcmp function call is placed into the variable of char type. The program is simply lucky.
  3. The reviewed comparison function is used very rarely or not used at all.
  4. Who said that the program is working? A lot of programs really do something wrong!

Recommendations

I demonstrated how many errors can be found in the comparison functions. It follows that the efficiency of these functions should be checked with unit-tests by all means.

It is really necessary to write unit-tests for the comparison operators, for Equals functions and so on.

I am quite sure that there was such an understanding among programmers before reading this article, that unit tests for such functions is extra work and they won't detect any errors anyway: the comparison functions are just so simple at the first glance... Well, now I showed the horror that can hide in them.

Code reviews and using static analysis tools would also be a great help.

Conclusion

In this article we mentioned a large amount of big-name projects that are developed by highly qualified experts. These projects are thoroughly tested using different methodologies. Still, it didn't stop PVS-Studio from finding errors in them. This shows that PVS-Studio can become a nice complement to other methodologies used to improve the quality and reliability of the code.

Use Intel® Optane™ Technology and Intel® 3D NAND SSDs with Red Hat Ceph* Storage

$
0
0

Ceph configuration

Download [1.9KB]

Introduction

As solid-state drives (SSDs) become more affordable, cloud providers are working to provide high-performance, highly reliable SSD-based storage for their customers. Red Hat Ceph* Storage, an open source scale-out storage solution, faces increasing demand from customers who wish to use SSDs in Ceph Storage to build high-performance storage solutions for their clouds.

The disruptive Intel® Optane™ Solid State Drive based on 3D XPoint™ technology fills the performance gap between DRAM and NAND-based SSDs. At the same time, Intel® 3D NAND TLC is reducing the cost gap between SSDs and traditional spindle hard drives, making all-flash storage an affordable option.

This article presents three Ceph Storage all-flash storage system reference designs, and provides Ceph Storage performance test results on the first Intel Optane and P4500 TLC NAND based all-flash cluster. This cluster delivers multi-million IOPS with extremely low latency as well as increased storage density with competitive dollar-per-gigabyte costs. It also shares Ceph Storage BlueStore tunings and optimizations, especially rocksdb tunings to mitigate the impact of compaction.

What Motivates Red Hat Ceph* Storage All-Flash Array Development

Several motivations are driving the development of Ceph-based all-flash storage systems. Cloud storage providers (CSPs) are struggling to deliver performance at increasingly massive scale. A common scenario is to build an Amazon EBS-like service for an OpenStack*-based public/private cloud, leading many CSPs to adopt Ceph-based all-flash storage systems. Meanwhile, there is strong demand to run enterprise applications in the cloud. For example, customers are adapting OLTP workloads to run on Ceph Storage when they migrate from traditional enterprise storage solutions. In addition to the major goal of leveraging the multi-purpose Ceph all-flash storage cluster to reduce TCO, performance is an important factor for these OLTP workloads. Moreover, with the steadily declining price of SSDs and efficiency-boosting technologies like deduplication and compression, an all-flash array (AFA) is becoming increasingly acceptable.

Intel® Optane™ and 3D NAND Technology

Intel® Optane™ technology provides an unparalleled combination of high throughput, low latency, high quality of service, and high endurance. It is a unique combination of 3D XPoint™ Memory Media, Intel Memory and Storage Controllers, Intel Interconnect IP and Intel® software1. Together these building blocks deliver a revolutionary leap forward in decreasing latency and accelerating systems for workloads demanding large capacity and fast storage.

Intel 3D NAND technology improves regular two-dimensional storage by stacking storage cells to increase capacity through higher density, lower cost per gigabyte, and offers the reliability, speed, and performance expected of solid-state memory3. It offers a cost-effective replacement for traditional hard-disk drives (HDDs) to help customers accelerate user experiences, improve the performance of apps and services across segments, and also reduce IT costs.

Intel Ceph Storage Reference Architecture

Based on different usage cases and application characteristics, Intel proposed three reference architectures (RAs) for Ceph-based all-flash array (AFA).

Standard configuration

Standard configuration is ideally suited for throughput optimized workloads that need high-capacity storage with good performance. We recommend using NVMe*/PCIe* SSD for journal and caching to achieve the best performance while balancing the cost. Table 1 describes the RA using 1x Intel® SSD DC P4600 Series as a journal or BlueStore* rocksdb write-ahead log (WAL) device, 12x up to 4 TB HDD as data drive.

NVMe/PCIe SSD for journal and caching, 12x HDD for data, Intel® Xeon® processor, Intel® Network Interface Card

Example: 1x 1.6 TB Intel SSD DC P4600 as a journal, Intel® Cache Acceleration Software, 12 HDDs, Intel® Xeon® processor E5-2650 v4 .

Table 1. Standard configuration.

Ceph Storage Node  configuration – Standard

CPU

Intel® Xeon® processor E5-2650 v4

Memory

64 GB

NIC

Single 10Gb E, Intel® 82599 10 Gigabit Ethernet Controller or Intel® Ethernet Controller X550

Storage

Data: 12 x 4 TB HDD
Journal or WAL: 1x Intel® SSD DC P4600 1.6 TB
Caching: P4600

Caching Software

Intel® Cache Acceleration Software 3.0, option: Intel® Rapid Storage Technology enterprise/MD4.3; open source cache-like bache/flashcache

TCO optimized

The TCO-optimized configuration provides the best possible performance for workloads that need higher performance, especially for throughput, IOPS, and SLAs with medium storage capacity requirements, leveraging a mixed of NVMe and SATA SSDs.

Table 2. TCO optimized configuration

Ceph Storage node –TCO Optimized

CPU

Intel® Xeon® processor E5-2690 v4

Memory

128 GB

NIC

Dual 10GbE (20 GB), Intel® 82599 10 Gigabit Ethernet Controller

Storage

Data: 4x Intel® SSD DC P4500 4, 8, or 16 TB or Intel DC SATA SSDs

Journal or WAL: 1x Intel® SSD DC P4600 Series 1.6 TB

IOPS optimized

The IOPS-optimized configuration provided best performance (throughput and latency) with Intel Optane Solid State Drives as Journal (FileStore) and WAL device (BlueStore) for a standalone Ceph cluster.

  • All NVMe/PCIe SSD Ceph system
  • Intel Optane Solid State Drive for FileStore Journal or BlueStore WAL
  • NVMe/PCIe SSD data, Intel Xeon processor, Intel® NICs
  • Example: 4x Intel SSD P4500 4, 8, or 16 TB for data, 1x Intel® Optane™ SSD DC P4800X 375 GB as journal (or WAL and database), Intel Xeon processor, Intel® NICs.

Table 3. IOPS optimized configuration

Ceph* Storage node –IOPS optimized

CPU

Intel® Xeon® processor E5-2699 v4

Memory

>= 128 GB

NIC

2x 40GbE (80 Gb), 4x Dual 10GbE (800 Gb), Intel® Ethernet Converged Network Adapter X710 family

Storage

Data: 4x Intel® SSD DC P4500 4, 8, or 16 TB

Journal or WAL : 1x Intel® Optane™ SSD DC P4800X 375 GB

Notes

  • Journal: Ceph supports multiple storage back-end. The most popular one is FileStore, based on a filesystem (for example, XFS*) to store its data. In FileStore, Ceph OSDs use a journal for speed and consistency. Using SSD as a journal device will significantly improve Ceph cluster performance.
  • WAL: BlueStore is a new storage back-end designed to replace FileStore in the near future. It overcomes several limitations of XFS and POSIX* that exist in FileStore. BlueStore consumes raw partitions directly to store the data, but the metadata comes with an OSD, which will be stored in Rocksdb. Rocksdb uses a write-ahead log to ensure data consistency.
  • The RA is not a fixed configuration. We will continue to refresh it with latest Intel® products.

Ceph All-Flash Array performance

This section presents a performance evaluation of the IOPS-optimized configuration based on Ceph BlueStore.

System configuration

The test system described in Table 4 consisted of five Ceph storage servers, each fitted with two Intel® Xeon® processors E5-2699 v4 CPUs and 128 GB memory, plus 1x Intel® SSD DC P3700 2TB as a BlueStore WAL device and x 4 T Intel® SSD DC P3520 2TB as a data drive, and 1x Intel® Ethernet Converged Network Adapters X710 NIC 40 Gb NIC, two ports bonding together through bonding mode 6, used as separate cluster and public network for Ceph, system topology described in Figure 1. The test system also consisted of 5 client nodes, each fitted with two Intel Xeon processors E5-2699 v4 and 64 GB memory and 1x Intel Ethernet Converged Network Adapters X710 NIC 40 Gb NIC, two ports bonding together through bonding mode 6.

Ceph 12.0.0 (Luminous dev) was used, and each Intel SSD DC P3520 Series runs 4 OSD daemons. The rbd pool used for the testing was configured with 2 replica.

Table 4. System configuration.

Ceph Storage node – IOPS optimized

CPU

Intel® Xeon® processor E5-2699 v4 2.20 GHz

Memory

128 GB

NIC

1x 40 G Intel® Ethernet Converged Network Adapters X710, two ports bonding mode 6

Disks

1x Intel® SSD DC P3700 (2T) + 4x Intel® SSD DC P3520 2 TB

Software configuration

Ubuntu* 14.04, Ceph 12.0.0

Diagram of cluster topology
Figure 1. Cluster topology.

Testing methodology

To simulate a typical usage scenario, four test patterns were selected using fio with librbd. It consisted of 4K random read and write, and 64K sequential read and write. For each pattern, the throughput (IOPS or bandwidth) was measured as performance metrics with the number of volumes scaling; the volume size was 30 GB. To get stable performance, the volumes were pre-allocated to bypass the performance impact of thin-provision. OSD page cache was dropped before each run to eliminate page cache impact. For each test case, fio was configured with a 100 seconds warm up and 300 seconds data collection. Detail fio testing parameters were included in the software configuration part.

Performance overview

Table 5 shows the promising performance after tuning on this five-node cluster. 64K sequential read and write throughput is 5630 MB/s and 4200 MB/s respectively (maximums with the Intel Ethernet Converged Network Adapters X710 NIC in bonding mode 6). 4 K random read throughput is 1312K IOPS with 1ms average latency, while 4 KB random write throughput is 331K IOPS with 4.8 ms average latency. The performance measured in the testing was roughly within expectations, unless a regression of 64K sequential write tests compared with previous Ceph releases, which requires further investigation and optimization.

Table 5. Performance overview.

Pattern

Throughput

Average Latency

64KB Sequential Write

4200 MB/s

18.9ms

64KB Sequential Read

5630 MB/s

17.7ms

4KB Random Write

331K IOPS

4.8ms

4KB Random Read

1312K IOPS

1.2ms

Scalability tests

Figures 2 to 5 show the graph of throughput for 4K random and 64K sequential workloads with different number of volumes, each fio was running in the volume with 16 queue depth.

Ceph demonstrated excellent 4K random read performance on the all-flash array reference architecture, as the total number of volumes increased from 1 to 100, the total 4K random read IOPS peaked around 1310 K IOPS, with an average latency around 1.2 ms. The total 4K random write IOPS peaked around 330K IOPS, with an average latency around 4.8 ms.

graphic of results for 4K Random read performance
Figure 2. 4K Random read performance.

graphic of results for 4K random write performance load line
Figure 3. 4K random write performance load line.

For 64K sequential read and write, as the total number of volumes increased from 1 to 100, the sequential read throughput peaked around 5630 MB/s, while sequential write peaked around 4200 MB/s. The sequential write throughput was lower than the previous Ceph release (11.0.2). It requires further investigation and optimization; stay tuned for further updates.

graphic of results for 64K sequential read throughput
Figure 4. 64K sequential read throughput

graphic of results for 64K sequential write throughput
Figure 5. 64K sequential write throughput

Latency Improvement with Intel® Optane™SSD

Fig 6 shows the latency comparison for 4K random write workloads with 1x Intel® SSD DC P3700 series 2.0TB and 1x Intel® Optane™ SSD DC P4800X series 375 GB drive as rocksdb & WAL device. The results proved with the Intel® Optane™ SSD DC P4800X series 375 GB SSD as rocksdb and WAL drive in Ceph BlueData, the latency was significantly reduced:  a 226% reduction in 99.99% latency.

graphic of results for 4K random read and 4K random write latency comparison
Figure 6. 4K random read and 4K random write latency comparison

Summary

Ceph is becoming one of most open source scale-out storage solutions, and there is a growing demands in build Ceph based high-performance all-flash array storage solutions for their clouds. We proposed three different reference architecture configurations targeting for different usage scenarios. The results of the testing that simulated different workload pattern demonstrated that a Ceph all-flash system could deliver very high performance with excellent latency.

Software configuration

Fio configuration used for the testing

Take 4K random read for example.

[global]
    direct=1
    time_based
[fiorbd-randread-4k-qd16-30g-100-300-rbd]
    rw=randread
    bs=4k
    iodepth=16
    ramp_time=100
    runtime=300
    ioengine=rbd
    clientname=${RBDNAME}
    pool=${POOLNAME}
    rbdname=${RBDNAME}
    iodepth_batch_submit=1
    iodepth_batch_complete=1
    norandommap
  1. http://www.intel.com/content/www/us/en/architecture-and-technology/intel-optane-technology.html
  2. http://ceph.com
  3. http://www.intel.com/content/www/us/en/solid-state-drives/3d-nand-technology-animation.html

This sample source code is released under the Intel Sample Source Code License Agreement.

How to Get Intel® MKL/IPP/DAAL

$
0
0

This page provides links to the current ways to get the Intel® performance library: Intel® Math Kernel Library, Intel® Integrated Performance Primitives, Intel® Data Analytics Acceleration Library( Intel® MKL/IPP/DAAL)

•   Sub-component of Intel Parallel Studio XE/Intel System Studio

     https://software.intel.com/en-us/intel-parallel-studio-xe
     https://software.intel.com/en-us/system-studio

The article provide the version information of Intel® performance library include in the bundles product: https://software.intel.com/en-us/articles/which-version-of-the-intel-ipp-intel-mkl-and-intel-tbb-libraries-are-included-in-the-intel

•   Free standalone access through separated product main page (Intel® MKL/IPP/DAAL)
    https://software.intel.com/en-us/mkl
    https://software.intel.com/en-us/intel-ipp
    https://software.intel.com/en-us/intel-daal

•   Free access through High Performance Library (Intel® MKL/IPP/DAAL)
    https://software.intel.com/en-us/performance-libraries
 


Only for Intel® MKL

•Cloudera* Parcels support since Intel® MKL2017 update 2
https://software.intel.com/en-us/articles/installing-intel-mkl-cloudera-cdh-parcel
•Conda* package/ Anaconda Cloud* support since Intel® MKL2017 update 2
https://software.intel.com/en-us/articles/using-intel-distribution-for-python-with-anaconda
 
The libraries gotten from above ways are exact same in functionality and performance.  The mainly differences  may in license agreement and upgrade/support way.
 

The Evil within the Comparison Functions

$
0
0

Perhaps, readers remember my article titled "Last line effect". It describes a pattern I've once noticed: in most cases programmers make an error in the last line of similar text blocks. Now I want to tell you about a new interesting observation. It turns out that programmers tend to make mistakes in functions comparing two objects. This statement looks implausible; however, I'll show you a great number of examples of errors that may be shocking to a reader. So, here is a new research, it will be quite amusing and scary.

Problematics

Here is my statement: programmers quite often make mistakes in rather simple functions that are meant to compare two objects. This claim is based on the experience of our team in checking a large number of open source projects in C, C++ and C#.

The functions we are going to consider here are IsEqual, Equals, Compare, AreEqual and so on or overloaded operators as ==, !=.

I noticed that when writing articles, very often I come across errors related to the comparison functions. I decided to explore this question in detail and examined the base of errors we found. I did a search of functions throughout the base containing words Cmp, Equal, Compare and such. The result was very impressive and shocking.

In fact this story is similar to the one we had when writing the article "Last line effect". Similarly, I noticed an anomaly and decided to explore it more carefully. Unfortunately, unlike the aforementioned article, I don't know how to bring statistics here and which figures to provide. Perhaps, later I'll come up with a solution with the statistics. At this point I am guided by intuition and can only share my feelings. They see that there are a lot of errors in the comparison functions and I am sure, you will get the same feeling when you see that huge amount of truly impressive examples.

Psychology

For a moment let's go back to the article "Last line effect". By the way, if you haven't read it, I suggest taking a break and looking at it. There is a more detailed analysis of this topic: "The last line effect explained"

In general, we can conclude that the cause of the errors in the last lined is related to the fact that the developer has already mentally moved to the new lines/tasks instead of focusing on the completion of the current fragment. As a result - when writing similar blocks of text, there is a higher probability that a programmer will make an error in the last one.

I believe that in the case of writing a comparison function, a developer in general often don't focus on it, considering it to be too trivial. In other words, he writes the code automatically, without thinking over it. Otherwise, it is not clear how one can make an error like this:

bool IsLuidsEqual(LUID luid1, LUID luid2)
{
  return (luid1.LowPart == luid2.LowPart) &&
         (luid2.HighPart == luid2.HighPart);
}

PVS-Studio analyzer detected this error in the code of RunAsAdmin Explorer Shim (C++) project: V501 There are identical sub-expressions to the left and to the right of the '==' operator: luid2.HighPart == luid2.HighPart RAACommon raacommonfuncs.cpp 1511

A typo. In the second line it should be: luid1.HighPart == luid2.HighPart.

The code is very simple. Apparently, the simplicity of code spoils everything. A programmer immediately thinks of the task to write such a function as standard and uninteresting. He instantly thinks of the way to write the function and he has just to implement the code. This is a routine, but unfortunately an inevitable process to start writing more important, complex and interesting code. He is already thinking about the new task... and as a result - makes an error.

In addition, programmers rarely write unit tests for such functions. Again the simplicity of these functions prevents from it. It seems that it would be too much to test them, as these functions are simple and repetitive. A person has written hundreds of such functions in his life, can he make an error in another function? Yes, he can and he does.

I would also like to note that we aren't talking about code of students who are just learning to program. We are talking about bugs in the code of such projects as GCC, Qt, GDB, LibreOffice, Unreal Engine, CryEngine 4 V Chromium, MongoDB, Oracle VM Virtual Box, FreeBSD, WinMerge, the CoreCLR, MySQL, Mono, CoreFX, Roslyn, MSBuild, etc. It's all very serious.

We are going to have a look at so many diverse examples that it would be scary to sleep at night.

Erroneous Patterns in Comparison Functions

All errors in comparison functions will be divided into several patterns. In the article we'll be talking about errors in projects in C, C++ and C#, but it makes no sense to separate these languages, as most of the patterns are similar for different languages.

Pattern: A < B, B > A

Very often in the comparison functions there is a need to make such checks:

  • A < B
  • A > B

Sometimes programmers think that is more elegant to use the same operator <, but to switch the variables.

  • A < B
  • B < A

However, due to the inattentiveness, we get such checks:

  • A < B
  • B > A

In fact, one and the same comparison is done twice here. Perhaps, it's not clear what it is about here, but we'll get to the practical examples and it'll all become clearer.

string _server;
....
bool operator<( const ServerAndQuery& other ) const {
  if ( ! _orderObject.isEmpty() )
    return _orderObject.woCompare( other._orderObject ) < 0;

  if ( _server < other._server )
    return true;
  if ( other._server > _server )
    return false;
  return _extra.woCompare( other._extra ) < 0;
}

PVS-Studio analyzer detected this error in the code of MongoDB (C++): V581 The conditional expressions of the 'if' operators situated alongside each other are identical. Check lines: 44, 46. parallel.h 46

This condition:

if ( other._server > _server )

Will always be false, as the same check was done two lines before. Correct code variant:

if ( _server < other._server )
  return true;
if ( other._server < _server )
  return false;

This error was detected in the code of Chromium project (C++):

enum ContentSettingsType;
struct EntryMapKey {
  ContentSettingsType content_type;
  ...
};

bool OriginIdentifierValueMap::EntryMapKey::operator<(
    const OriginIdentifierValueMap::EntryMapKey& other) const {
  if (content_type < other.content_type)
    return true;
  else if (other.content_type > content_type)
    return false;
  return (resource_identifier < other.resource_identifier);
}

PVS-Studio warning: V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 61, 63. browser content_settings_origin_identifier_value_map.cc 61

That was a C++ example, now it's C# turn. The next error was found in the code of IronPython and IronRuby (C#).

public static int Compare(SourceLocation left,
                          SourceLocation right) {
  if (left < right) return -1;
  if (right > left) return 1;
  return 0;
}

PVS-Studio warning (C#): V3021 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains method return. This means that the second 'if' statement is senseless. SourceLocation.cs 156

I think there is no need in explanation.

Note. For C# there was just one example of an error, but for C++ - two. In general, there will be less bugs in the C# code, than for C/C++. But I do not recommend rushing to the conclusion that C# is much safer. The thing is that PVS-Studio analyzer has only recently learned to check C# code relatively recently, and we have just checked less projects written in C#, than in C and C++.

Pattern: a Member of the Class is Compared with itself

The comparison functions usually consist of successive comparisons of structure/class members. This code tends to be more erronreous, when the member of the class starts being compared with itself. I can specify two subtypes of errors.

In the first case, a programmer forgets to specify the name of the object and writes in the following way:

return m_x == foo.m_x &&
       m_y == m_y &&            // <=
       m_z == foo.m_z;
In the second case, the same name of the object is written.
return zzz.m_x == foo.m_x &&
       zzz.m_y == zzz.m_y &&    // <=
       zzz.m_z == foo.m_z;

Let's take a closer look at practical examples of this pattern. Pay attention that incorrect comparison often occurs in the last block of similar code blocks, which reminds us of the "last line effect" again.

The error is found in the code of Unreal Engine 4 (C++) project:

bool
Compare(const FPooledRenderTargetDesc& rhs, bool bExact) const
{
  ....
  return Extent == rhs.Extent&& Depth == rhs.Depth&& bIsArray == rhs.bIsArray&& ArraySize == rhs.ArraySize&& NumMips == rhs.NumMips&& NumSamples == rhs.NumSamples&& Format == rhs.Format&& LhsFlags == RhsFlags&& TargetableFlags == rhs.TargetableFlags&& bForceSeparateTargetAndShaderResource ==
         rhs.bForceSeparateTargetAndShaderResource&& ClearValue == rhs.ClearValue&& AutoWritable == AutoWritable;           // <=
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: AutoWritable == AutoWritable rendererinterface.h 180

The code of Samba (C) project:

static int compare_procids(const void *p1, const void *p2)
{
  const struct server_id *i1 = (struct server_id *)p1;
  const struct server_id *i2 = (struct server_id *)p2;

  if (i1->pid < i2->pid) return -1;
  if (i2->pid > i2->pid) return 1;
  return 0;
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '>' operator: i2->pid > i2->pid brlock.c 1901

The code of MongoDB (C++) project:

bool operator==(const MemberCfg& r) const {
  ....
  return _id==r._id && votes == r.votes &&
         h == r.h && priority == r.priority &&
         arbiterOnly == r.arbiterOnly &&
         slaveDelay == r.slaveDelay &&
         hidden == r.hidden &&
         buildIndexes == buildIndexes;        // <=
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: buildIndexes == buildIndexes rs_config.h 101

The code of Geant4 Software (C++) project:

inline G4bool G4FermiIntegerPartition::
operator==(const G4FermiIntegerPartition& right)
{
  return (total == right.total &&
          enableNull == enableNull &&          // <=
          partition == right.partition);
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: enableNull == enableNull G4hadronic_deex_fermi_breakup g4fermiintegerpartition.icc 58

The code of LibreOffice (C++) project:

class SvgGradientEntry
{
  ....
  bool operator==(const SvgGradientEntry& rCompare) const
  {
    return (getOffset() == rCompare.getOffset()&& getColor() == getColor()            // <=&& getOpacity() == getOpacity());      // <=
  }
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: getColor() == getColor() svggradientprimitive2d.hxx 61

The code of Chromium (C++) project:

bool FileIOTest::MatchesResult(const TestStep& a,
                               const TestStep& b) {
  ....
  return (a.data_size == a.data_size &&             // <=
          std::equal(a.data, a.data + a.data_size, b.data));
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: a.data_size == a.data_size cdm_file_io_test.cc 367

The code of FreeCAD (C++) project:

bool FaceTypedBSpline::isEqual(const TopoDS_Face &faceOne,
                               const TopoDS_Face &faceTwo) const
{
  ....
  if (surfaceOne->IsURational() !=
      surfaceTwo->IsURational())
    return false;
  if (surfaceTwo->IsVRational() !=         // <=
      surfaceTwo->IsVRational())           // <=
    return false;
  if (surfaceOne->IsUPeriodic() !=
      surfaceTwo->IsUPeriodic())
    return false;
  if (surfaceOne->IsVPeriodic() !=
      surfaceTwo->IsVPeriodic())
    return false;
  if (surfaceOne->IsUClosed() !=
      surfaceTwo->IsUClosed())
    return false;
  if (surfaceOne->IsVClosed() !=
      surfaceTwo->IsVClosed())
    return false;
  if (surfaceOne->UDegree() !=
      surfaceTwo->UDegree())
    return false;
  if (surfaceOne->VDegree() !=
      surfaceTwo->VDegree())
    return false;
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions 'surfaceTwo->IsVRational()' to the left and to the right of the '!=' operator. modelrefine.cpp 780

The code of Serious Engine (C++) project:

class CTexParams {
public:

  inline BOOL IsEqual( CTexParams tp) {
    return tp_iFilter     == tp.tp_iFilter &&
           tp_iAnisotropy == tp_iAnisotropy &&             // <=
           tp_eWrapU      == tp.tp_eWrapU &&
           tp_eWrapV      == tp.tp_eWrapV; };
  ....
};

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '==' operator: tp_iAnisotropy == tp_iAnisotropy gfx_wrapper.h 180

The code of Qt (C++) project:

inline bool qCompare(QImage const &t1, QImage const &t2, ....)
{
  ....
  if (t1.width() != t2.width() || t2.height() != t2.height()) {
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '!=' operator: t2.height() != t2.height() qtest_gui.h 101

The code of FreeBSD (C) project:

static int
compare_sh(const void *_a, const void *_b)
{
  const struct ipfw_sopt_handler *a, *b;

  a = (const struct ipfw_sopt_handler *)_a;
  b = (const struct ipfw_sopt_handler *)_b;
  ....
  if ((uintptr_t)a->handler < (uintptr_t)b->handler)
    return (-1);
  else if ((uintptr_t)b->handler > (uintptr_t)b->handler) // <=
    return (1);

  return (0);
}

PVS-Studio warning: V501 There are identical sub-expressions '(uintptr_t) b->handler' to the left and to the right of the '>' operator. ip_fw_sockopt.c 2893

The code of Mono (C#) project:

static bool AreEqual (VisualStyleElement value1,
                      VisualStyleElement value2)
{
  return
    value1.ClassName == value1.ClassName && // <=
    value1.Part == value2.Part &&
    value1.State == value2.State;
}

PVS-Studio warning: V3001 There are identical sub-expressions 'value1.ClassName' to the left and to the right of the '==' operator. ThemeVisualStyles.cs 2141

The code of Mono (C#) project:

public int ExactInference (TypeSpec u, TypeSpec v)
{
  ....
  var ac_u = (ArrayContainer) u;
  var ac_v = (ArrayContainer) v;
  ....
  var ga_u = u.TypeArguments;
  var ga_v = v.TypeArguments;
  ....
  if (u.TypeArguments.Length != u.TypeArguments.Length) // <=
    return 0;

  ....
}

PVS-Studio warning: V3001 There are identical sub-expressions 'u.TypeArguments.Length' to the left and to the right of the '!=' operator. generic.cs 3135

The code of MonoDevelop (C#) project:

Accessibility DeclaredAccessibility { get; }
bool IsStatic { get; }

private bool MembersMatch(ISymbol member1, ISymbol member2)
{
  if (member1.Kind != member2.Kind)
  {
    return false;
  }

  if (member1.DeclaredAccessibility !=          // <=1
      member1.DeclaredAccessibility             // <=1
   || member1.IsStatic != member1.IsStatic)     // <=2
  {
    return false;
  }

  if (member1.ExplicitInterfaceImplementations().Any() ||
      member2.ExplicitInterfaceImplementations().Any())
  {
    return false;
  }

  return SignatureComparer
    .HaveSameSignatureAndConstraintsAndReturnTypeAndAccessors(
       member1, member2, this.IsCaseSensitive);
}

PVS-Studio warning: V3001 There are identical sub-expressions 'member1.IsStatic' to the left and to the right of the '!=' operator. CSharpBinding AbstractImplementInterfaceService.CodeAction.cs 545

The code of Haiku (C++) project:

int __CORTEX_NAMESPACE__ compareTypeAndID(....)
{
  int retValue = 0;
  ....
  if (lJack && rJack)
  {
    if (lJack->m_jackType < lJack->m_jackType)           // <=
    {
      return -1;
    }
    if (lJack->m_jackType == lJack->m_jackType)          // <=
    {
      if (lJack->m_index < rJack->m_index)
      {
        return -1;
      }
      else
      {
        return 1;
      }
    }
    else if (lJack->m_jackType > rJack->m_jackType)
    {
      retValue = 1;
    }
  }
  return retValue;
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '<' operator: lJack->m_jackType < lJack->m_jackType MediaJack.cpp 783

Just below there is exactly the same error. As I understand, in both cases a programmer forgot to replace lJack with rJack.

The code of CryEngine V (C++) project:

bool
CompareRotation(const Quat& q1, const Quat& q2, float epsilon)
{
  return (fabs_tpl(q1.v.x - q2.v.x) <= epsilon)&& (fabs_tpl(q1.v.y - q2.v.y) <= epsilon)&& (fabs_tpl(q2.v.z - q2.v.z) <= epsilon)     // <=&& (fabs_tpl(q1.w - q2.w) <= epsilon);
}

PVS-Studio warning: V501 There are identical sub-expressions to the left and to the right of the '-' operator: q2.v.z - q2.v.z entitynode.cpp 93

Pattern: Evaluating the Size of a Pointer Instead of the Size of the Structure/Class

This type of error occurs in programs written in C and C++ and is caused by incorrect use of the sizeof operator. The error in evaluating not the size of the object, but the size of the pointer. Example:

T *a = foo1();
T *b = foo2();
x = memcmp(a, b, sizeof(a));

Instead of the size of the T structure, a size of the pointer gets evaluated. The size of the pointer depends on the used data model, but usually it is 4 or 8. As a result, more or less bites in the memory get compared than take the structure.

Correct variant of the code:

x = memcmp(a, b, sizeof(T));

or

x = memcmp(a, b, sizeof(*a));

Now let's move on to the practical part. Here is how such a bug looks in the code of CryEngine V (C++) code:

bool
operator==(const SComputePipelineStateDescription& other) const
{
  return 0 == memcmp(this, &other, sizeof(this));
}

PVS-Studio warning: V579 The memcmp function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. graphicspipelinestateset.h 58

The code of Unreal Engine 4 project (C++):

bool FRecastQueryFilter::IsEqual(
  const INavigationQueryFilterInterface* Other) const
{
  // @NOTE: not type safe, should be changed when
  // another filter type is introduced
  return FMemory::Memcmp(this, Other, sizeof(this)) == 0;

}

PVS-Studio warning: V579 The Memcmp function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. pimplrecastnavmesh.cpp 172

Pattern: Repetitive Arguments of Cmp(A, A) Type

Comparison functions usually call other comparison functions. At the same time one of the possible errors is that the reference/pointer is passed to the same object twice. Example:

x = memcmp(A, A, sizeof(T));

Here the object A will be compared with itself, which, is of course, has no sense.

We'll start with an error, found in the debugger GDB (C):

static int
psymbol_compare (const void *addr1, const void *addr2,
                 int length)
{
  struct partial_symbol *sym1 = (struct partial_symbol *) addr1;
  struct partial_symbol *sym2 = (struct partial_symbol *) addr2;

  return (memcmp (&sym1->ginfo.value, &sym1->ginfo.value,    // <=
                  sizeof (sym1->ginfo.value)) == 0&& sym1->ginfo.language == sym2->ginfo.language&& PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2)&& PSYMBOL_CLASS (sym1) == PSYMBOL_CLASS (sym2)&& sym1->ginfo.name == sym2->ginfo.name);
}

PVS-Studio warning: V549 The first argument of 'memcmp' function is equal to the second argument. psymtab.c 1580

The code of CryEngineSDK project (C++):

inline bool operator != (const SEfResTexture &m) const
{
  if (stricmp(m_Name.c_str(), m_Name.c_str()) != 0 ||   // <=
      m_TexFlags != m.m_TexFlags ||
      m_bUTile != m.m_bUTile ||
      m_bVTile != m.m_bVTile ||
      m_Filter != m.m_Filter ||
      m_Ext != m.m_Ext ||
      m_Sampler != m.m_Sampler)
    return true;
  return false;
}

PVS-Studio warning: V549 The first argument of 'stricmp' function is equal to the second argument. ishader.h 2089

The code of PascalABC.NET (C#):

private List<string> enum_consts = new List<string>();
public override bool IsEqual(SymScope ts)
{
  EnumScope es = ts as EnumScope;
  if (es == null) return false;
  if (enum_consts.Count != es.enum_consts.Count) return false;
  for (int i = 0; i < es.enum_consts.Count; i++)
    if (string.Compare(enum_consts[i],
                       this.enum_consts[i], true) != 0)
      return false;
  return true;
}

PVS-Studio warning: V3038 The 'enum_consts[i]' argument was passed to 'Compare' method several times. It is possible that other argument should be passed instead. CodeCompletion SymTable.cs 2206

I'll give some explanation here. The error in the factual arguments of the Compare function:

string.Compare(enum_consts[i], this.enum_consts[i], true)

The thing is that enum_consts[i] and this.enum_consts[i are the same things. As I understand, a correct call should be like this:

string.Compare(es.enum_consts[i], this.enum_consts[i], true)

or

string.Compare(enum_consts[i], es.enum_consts[i], true)

Pattern: Repetitive Checks A==B && A==B

Quite a common error in programming is when the same check is done twice. Example:

return A == B &&
       C == D &&   // <=
       C == D &&   // <=
       E == F;

Two variants are possible in this case. The first is quite harmless: one comparison is redundant and can be simply removed. The second is worse: some other variables were to be compared, but a programmer made a typo.

In any case, such code deserves close attention. Let me scare you a little more, and show that this error can be found even in the code of GCC compiler (C):

static bool
dw_val_equal_p (dw_val_node *a, dw_val_node *b)
{
  ....
  case dw_val_class_vms_delta:
    return (!strcmp (a->v.val_vms_delta.lbl1,
                     b->v.val_vms_delta.lbl1)&& !strcmp (a->v.val_vms_delta.lbl1,
                        b->v.val_vms_delta.lbl1));
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions '!strcmp(a->v.val_vms_delta.lbl1, b->v.val_vms_delta.lbl1)' to the left and to the right of the '&&' operator. dwarf2out.c 1428

The function strcmp is called twice with the same set of arguments.

The code of Unreal Engine 4 project (C++):

FORCEINLINE
bool operator==(const FShapedGlyphEntryKey& Other) const
{
  return FontFace == Other.FontFace&& GlyphIndex == Other.GlyphIndex   // <=&& FontSize == Other.FontSize&& FontScale == Other.FontScale&& GlyphIndex == Other.GlyphIndex;  // <=
}

PVS-Studio warning: V501 There are identical sub-expressions 'GlyphIndex == Other.GlyphIndex' to the left and to the right of the '&&' operator. fontcache.h 139

The code of Serious Engine project (C++):

inline BOOL CValuesForPrimitive::operator==(....)
{
  return (
 (....) &&
 (vfp_ptPrimitiveType == vfpToCompare.vfp_ptPrimitiveType) &&
 ....
 (vfp_ptPrimitiveType == vfpToCompare.vfp_ptPrimitiveType) &&
 ....
);

PVS-Studio warning: V501 There are identical sub-expressions '(vfp_ptPrimitiveType == vfpToCompare.vfp_ptPrimitiveType)' to the left and to the right of the '&&' operator. worldeditor.h 580

The code of Oracle VM Virtual Box project (C++):

typedef struct SCMDIFFSTATE
{
  ....
  bool  fIgnoreTrailingWhite;
  bool  fIgnoreLeadingWhite;
  ....
} SCMDIFFSTATE;
/* Pointer to a diff state. */

typedef SCMDIFFSTATE *PSCMDIFFSTATE;

/* Compare two lines */
DECLINLINE(bool) scmDiffCompare(PSCMDIFFSTATE pState, ....)
{
  ....
  if (pState->fIgnoreTrailingWhite    // <=
   || pState->fIgnoreTrailingWhite)   // <=
    return scmDiffCompareSlow(....);
  ....
}

PVS-Studio warning: V501 There are identical sub-expressions 'pState->fIgnoreTrailingWhite' to the left and to the right of the '||' operator. scmdiff.cpp 238

Pattern: Incorrect Use of the Value, Returned by memcmp Function

The memcmp function returns the following values of int type:

  • < 0 - buf1 less than buf2;
  • 0 - buf1 identical to buf2;
  • > 0 - buf1 greater than buf2;

Please note that '>0' can be any number, not only 1. These numbers can be: 2, 3, 100, 256, 1024, 5555, 65536 and so on. This means that this result cannot be placed to a variable of the char and short type. The high bits can be lost, which might violate the logic of program execution.

Also this means that the result cannot be compared with constants 1 or -1. In other words, it is wrong to write this:

if (memcmp(a, b, sizeof(T)) == 1)
if (memcmp(x, y, sizeof(T)) == -1)

Correct comparisons:

if (memcmp(a, b, sizeof(T)) > 0)
if (memcmp(a, b, sizeof(T)) < 0)

The danger of this code is that it may successfully work for a long time. The errors may start showing up when moving to a new platform or with the change of the compiler version.

The code of ReactOS project (C++):

HRESULT WINAPI CRecycleBin::CompareIDs(....)
{
  ....
  return MAKE_HRESULT(SEVERITY_SUCCESS, 0,
   (unsigned short)memcmp(pidl1->mkid.abID,
                          pidl2->mkid.abID,
                          pidl1->mkid.cb));
}

PVS-Studio warning: V642 Saving the 'memcmp' function result inside the 'unsigned short' type variable is inappropriate. The significant bits could be lost breaking the program's logic. recyclebin.cpp 542

The code of Firebird project (C++):

SSHORT TextType::compare(ULONG len1, const UCHAR* str1,
ULONG len2, const UCHAR* str2)
{
  ....
  SSHORT cmp = memcmp(str1, str2, MIN(len1, len2));

  if (cmp == 0)
    cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0));
  return cmp;
}

PVS-Studio warning: V642 Saving the 'memcmp' function result inside the 'short' type variable is inappropriate. The significant bits could be lost breaking the program's logic. texttype.cpp 338

The code of CoreCLR project (C++):

bool operator( )(const GUID& _Key1, const GUID& _Key2) const
  { return memcmp(&_Key1, &_Key2, sizeof(GUID)) == -1; }

PVS-Studio warning: V698 Expression 'memcmp(....) == -1' is incorrect. This function can return not only the value '-1', but any negative value. Consider using 'memcmp(....) < 0' instead. sos util.cpp 142

The code of OpenToonz project (C++):

bool TFilePath::operator<(const TFilePath &fp) const
{
  ....
  char differ;
  differ = _wcsicmp(iName.c_str(), jName.c_str());
  if (differ != 0)
    return differ < 0 ? true : false;
  ....
}

PVS-Studio warning: V642 Saving the '_wcsicmp' function result inside the 'char' type variable is inappropriate. The significant bits could be lost, breaking the program's logic. tfilepath.cpp 328

Pattern: Incorrect Check of Null References

This error pattern is typical for C# programs. Sometimes in the comparison functions programmers write the type casting with the help of the as operator. The error is that inadvertently a programmer verifies against null not the new reference, but the original one. Let's take a look at a synthetic example:

ChildT foo = obj as ChildT;
if (obj == null)
  return false;
if (foo.zzz()) {}

The check if (obj == null) protects from the situation, if the obj variable contains a null reference. However, there is no protection from the case if it turns out that the as operator returns a null reference. The correct code should be like this:

ChildT foo = obj as ChildT;
if (foo == null)
  return false;
if (foo.zzz()) {}

Typically, this error occurs due to negligence of the programmer. Similar bugs are possible in the programs in C and C++, but I haven't found such a case in our error base.

The code of MonoDevelop project (C#):

public override bool Equals (object o)
{
  SolutionItemReference sr = o as SolutionItemReference;
  if (o == null)
    return false;
  return (path == sr.path) && (id == sr.id);
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'o', 'sr'. MonoDevelop.Core SolutionItemReference.cs 81

The code of CoreFX (C#):

public override bool Equals(object comparand)
{
  CredentialHostKey comparedCredentialKey =
                                  comparand as CredentialHostKey;

  if (comparand == null)
  {
    // This covers also the compared == null case
    return false;
  }

  bool equals = string.Equals(AuthenticationType,
        comparedCredentialKey.AuthenticationType, ....
  ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'comparand', 'comparedCredentialKey'. CredentialCache.cs 4007

The code of Roslyn project (C#):

public override bool Equals(object obj)
{
  var d = obj as DiagnosticDescription;

  if (obj == null)
    return false;

  if (!_code.Equals(d._code))
    return false;
  ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'd'. DiagnosticDescription.cs 201

The code of Roslyn (C#):

protected override bool AreEqual(object other)
{
  var otherResourceString = other as LocalizableResourceString;
  return
    other != null &&
    _nameOfLocalizableResource ==
      otherResourceString._nameOfLocalizableResource &&
    _resourceManager == otherResourceString._resourceManager &&
    _resourceSource == otherResourceString._resourceSource &&
    ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'other', 'otherResourceString'. LocalizableResourceString.cs 121

The code of MSBuild project (C#):

public override bool Equals(object obj)
{
   AssemblyNameExtension name = obj as AssemblyNameExtension;
   if (obj == null)  // <=
   {
     return false;
   }
   ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'name'. AssemblyRemapping.cs 64

The code of Mono project (C#):

public override bool Equals (object o)
{
  UrlMembershipCondition umc = (o as UrlMembershipCondition);
  if (o == null)                                      // <=
    return false;

  ....

  return (String.Compare (u, 0, umc.Url, ....) == 0); // <=
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'o', 'umc'. UrlMembershipCondition.cs 111

The code of Media Portal 2 project (C#):

public override bool Equals(object obj)
{
  EpisodeInfo other = obj as EpisodeInfo;
  if (obj == null) return false;
  if (TvdbId > 0 && other.TvdbId > 0)
    return TvdbId == other.TvdbId;
  ....
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'other'. EpisodeInfo.cs 560

The code of NASA World Wind project (C#):

public int CompareTo(object obj)
{
  RenderableObject robj = obj as RenderableObject;
  if(obj == null)                                 // <=
    return 1;
  return this.m_renderPriority.CompareTo(robj.RenderPriority);
}

PVS-Studio warning: V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'robj'. RenderableObject.cs 199

Pattern: Incorrect Loops

In some functions, collections of items are compared. Of course, different variant of the loops are used for its comparison. If a programmer writes the code inattentively, it's easy to mix something up, as it is with the comparison functions. Let's look at a few of these situations.

The code of Trans-Proteomic Pipeline (C++):

bool Peptide::operator==(Peptide& p) {
  ....
  for (i = 0, j = 0;
       i < this->stripped.length(), j < p.stripped.length();
       i++, j++) {
  ....
}

PVS-Studio warning: V521 Such expressions using the ',' operator are dangerous. Make sure the expression is correct. tpplib peptide.cpp 191

Note that the comma operator is used in the condition. The code is clearly incorrect, because the condition, written to the left of the coma is ignored. That is, the condition on the left is evaluated, but its result is not used in any way.

The code of Qt project (C++):

bool equals( class1* val1, class2* val2 ) const
{
  ...
  size_t size = val1->size();
  ...
  while ( --size >= 0 ){
    if ( !comp(*itr1,*itr2) )
      return false;
    itr1++;
    itr2++;
  }
  ...
}

PVS-Studio warning: V547 Expression '-- size >= 0' is always true. Unsigned type value is always >= 0. QtCLucene arrays.h 154

The code of CLucene project (C++):

class Arrays
{
  ....
   bool equals( class1* val1, class2* val2 ) const{
     static _comparator comp;
     if ( val1 == val2 )
       return true;
     size_t size = val1->size();
     if ( size != val2->size() )
       return false;
     _itr1 itr1 = val1->begin();
     _itr2 itr2 = val2->begin();
     while ( --size >= 0 ){
       if ( !comp(*itr1,*itr2) )
         return false;
       itr1++;
       itr2++;
     }
   return true;
  }
  ....
}

PVS-Studio warning: V547 Expression '-- size >= 0' is always true. Unsigned type value is always >= 0. arrays.h 154

The code of Mono project (C#):

public override bool Equals (object obj)
{
  ....
  for (int i=0; i < list.Count; i++) {
    bool found = false;
    for (int j=0; i < ps.list.Count; j++) {     // <=
      if (list [i].Equals (ps.list [j])) {
        found = true;
        break;
      }
    }
    if (!found)
      return false;
  }
  return true;
}

PVS-Studio warning: V3015 It is likely that a wrong variable is being compared inside the 'for' operator. Consider reviewing 'i' corlib-net_4_x PermissionSet.cs 607

Apparently, there is a typo here, and the variable j instead of i should be used in the nested loop:

for (int j=0; j < ps.list.Count; j++)

Pattern: A = getA(), B = GetA()

Quite often in the comparison functions a programmer has to write code of this kind:

if (GetA().x == GetB().x && GetA().y == GetB().y)

Intermediate variables are used to reduce the size of the conditions or for optimization:

Type A = GetA();
Type B = GetB();
if (A.x == B.x && A.y == B.y)

But inadvertently, a person sometimes makes a mistake and initializes temporary variables with the same value:

Type A = GetA();
Type B = GetA();

Now let's take a look at these errors in the code of real applications.

The code of LibreOffice project (C++):

bool CmpAttr(
  const SfxPoolItem& rItem1, const SfxPoolItem& rItem2)
{
  ....
  bool bNumOffsetEqual = false;
  ::boost::optional<sal_uInt16> oNumOffset1 =
        static_cast<const SwFmtPageDesc&>(rItem1).GetNumOffset();
  ::boost::optional<sal_uInt16> oNumOffset2 =
        static_cast<const SwFmtPageDesc&>(rItem1).GetNumOffset();

  if (!oNumOffset1 && !oNumOffset2)
  {
    bNumOffsetEqual = true;
  }
  else if (oNumOffset1 && oNumOffset2)
  {
    bNumOffsetEqual = oNumOffset1.get() == oNumOffset2.get();
  }
  else
  {
    bNumOffsetEqual = false;
  }
  ....
}

PVS-Studio warning: V656 Variables 'oNumOffset1', 'oNumOffset2' are initialized through the call to the same function. It's probably an error or un-optimized code. Check lines: 68, 69. findattr.cxx 69

The code of Qt project (C++):

AtomicComparator::ComparisonResult
IntegerComparator::compare(const Item &o1,
                           const AtomicComparator::Operator,
                           const Item &o2) const
{
  const Numeric *const num1 = o1.as<Numeric>();
  const Numeric *const num2 = o1.as<Numeric>();

  if(num1->isSigned() || num2->isSigned())
  ....
}

PVS-Studio warning: V656 Variables 'num1', 'num2' are initialized through the call to the same function. It's probably an error or un-optimized code. Consider inspecting the 'o1.as < Numeric > ()' expression. Check lines: 220, 221. qatomiccomparators.cpp 221

Pattern: Sloppy Copying of the Code

A large amount of errors, cited previously can be called the consequences of sloppy Copy-Paste. They fell under some categories of the erroneous pattern and I decided that it would be logical to describe them in corresponding sections. However, I have several errors that have clearly appeared because of sloppy code copying, but I have no idea how to classify them. That's why I collected these errors here.

The code of CoreCLR project (C++):

int __cdecl Compiler::RefCntCmp(const void* op1, const void* op2)
{
  ....
  if (weight1)
  {
    ....
    if (varTypeIsGC(dsc1->TypeGet()))
    {
      weight1 += BB_UNITY_WEIGHT / 2;
    }
    if (dsc1->lvRegister)
    {
      weight1 += BB_UNITY_WEIGHT / 2;
    }
  }

  if (weight1)
  {
    ....
    if (varTypeIsGC(dsc2->TypeGet()))
    {
      weight1 += BB_UNITY_WEIGHT / 2;       // <=
    }
    if (dsc2->lvRegister)
    {
      weight2 += BB_UNITY_WEIGHT / 2;
    }
  }
  ....
}

PVS-Studio warning: V778 Two similar code fragments were found. Perhaps, this is a typo and 'weight2' variable should be used instead of 'weight1'. clrjit lclvars.cpp 2702

The function was long that's why it is shortened for the article. If we examine the code of the function, we'll see that a part of the code was copied, but in one fragment a programmer forgot to replace the variable weight1 with weight2.

The code of WPF samples by Microsoft project (C#):

public int Compare(GlyphRun a, GlyphRun b)
{
  ....
  if (aPoint.Y > bPoint.Y)      // <=
  {
    return -1;
  }
  else if (aPoint.Y > bPoint.Y) // <=
  {
    result = 1;
  }
  else if (aPoint.X < bPoint.X)
  {
    result = -1;
  }
  else if (aPoint.X > bPoint.X)
  {
    result = 1;
  }
  ....
}

PVS-Studio warning: V3003 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 418, 422. txtserializerwriter.cs 418

The code of PascalABC.NET project (C#):

public void CompareInternal(....)
{
  ....
  else if (left is int64_const)
    CompareInternal(left as int64_const, right as int64_const);
  ....
  else if (left is int64_const)
    CompareInternal(left as int64_const, right as int64_const);
  ....
}

PVS-Studio warning: V3003 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 597, 631. ParserTools SyntaxTreeComparer.cs 597

The code of SharpDevelop project (C#):

public int Compare(SharpTreeNode x, SharpTreeNode y)
{
  ....
  if (typeNameComparison == 0) {
    if (x.Text.ToString().Length < y.Text.ToString().Length)
      return -1;
    if (x.Text.ToString().Length < y.Text.ToString().Length)
      return 1;
  }
  ....
}

PVS-Studio warning: V3021 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains method return. This means that the second 'if' statement is senseless NamespaceTreeNode.cs 87

The code of Coin3D (C++):

int
SbProfilingData::operator == (const SbProfilingData & rhs) const
{
  if (this->actionType != rhs.actionType) return FALSE;
  if (this->actionStartTime != rhs.actionStopTime) return FALSE;
  if (this->actionStartTime != rhs.actionStopTime) return FALSE;
  ....
}

PVS-Studio warning: V649 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains function return. This means that the second 'if' statement is senseless. Check lines: 1205, 1206. sbprofilingdata.cpp 1206

The code of Spring (C++):

bool operator < (const aiFloatKey& o) const
  {return mTime < o.mTime;}
bool operator > (const aiFloatKey& o) const
  {return mTime < o.mTime;}

PVS-Studio warning: V524 It is odd that the body of '>' function is fully equivalent to the body of '<' function. assimp 3dshelper.h 470

And here is the last, particularly interesting code fragment that PVS-Studio analyzer found in MySQL project (C++).

static int rr_cmp(uchar *a,uchar *b)
{
  if (a[0] != b[0])
    return (int) a[0] - (int) b[0];
  if (a[1] != b[1])
    return (int) a[1] - (int) b[1];
  if (a[2] != b[2])
    return (int) a[2] - (int) b[2];
  if (a[3] != b[3])
    return (int) a[3] - (int) b[3];
  if (a[4] != b[4])
    return (int) a[4] - (int) b[4];
  if (a[5] != b[5])
    return (int) a[1] - (int) b[5]; // <=
  if (a[6] != b[6])
    return (int) a[6] - (int) b[6];
  return (int) a[7] - (int) b[7];
}

PVS-Studio warning: V525 The code containing the collection of similar blocks. Check items '0', '1', '2', '3', '4', '1', '6' in lines 680, 682, 684, 689, 691, 693, 695. sql records.cc 680

Most likely, a programmer wrote the first comparison, then the second and got bored. So he copied to the buffer a text block:

if (a[1] != b[1])
  return (int) a[1] - (int) b[1];

A pasted it to the text of the program as many times as he needed. Then he changed indexes, but made a mistake in one place and got an incorrect comparison:

if (a[5] != b[5])
  return (int) a[1] - (int) b[5];

Note. I discuss this error in more detail in my mini-book "The Ultimate Question of Programming, Refactoring, and Everything" (see a chapter "Don't do the compiler's job").

Pattern: Equals Method Incorrectly Processes a Null Reference

In C# the accepted practice is to implement the Equals methods in such a way, so that they correctly process a situation, if a null reference is passed as an argument. Unfortunately, not all the methods are implemented according to this rule.

The code of GitExtensions (C#):

public override bool Equals(object obj)
{
  return GetHashCode() == obj.GetHashCode(); // <=
}

PVS-Studio warning: V3115 Passing 'null' to 'Equals(object obj)' method should not result in 'NullReferenceException'. Git.hub Organization.cs 14

The code of PascalABC.NET project (C#):

public override bool Equals(object obj)
{
  var rhs = obj as ServiceReferenceMapFile;
  return FileName == rhs.FileName;
}

PVS-Studio warning: V3115 Passing 'null' to 'Equals' method should not result in 'NullReferenceException'. ICSharpCode.SharpDevelop ServiceReferenceMapFile.cs 31

Miscellaneous Errors

The code of G3D Content Pak project (C++):

bool Matrix4::operator==(const Matrix4& other) const {
  if (memcmp(this, &other, sizeof(Matrix4) == 0)) {
    return true;
  }
  ...
}

PVS-Studio warning: V575 The 'memcmp' function processes '0' elements. Inspect the 'third' argument. graphics3D matrix4.cpp 269

One closing bracket is put incorrectly. As a result, the amount of bites compared is evaluated by the statement sizeof(Matrix4) == 0. The size of any class is more than 0, which means that the result of the expression is 0. Thus, 0 bites get compared.

Correct variant:

if (memcmp(this, &other, sizeof(Matrix4)) == 0) {

The code of Wolfenstein 3D project (C++):

inline int operator!=( quat_t a, quat_t b )
{
  return ( ( a.x != b.x ) || ( a.y != b.y ) ||
           ( a.z != b.z ) && ( a.w != b.w ) );
}

PVS-Studio warning: V648 Priority of the '&&' operation is higher than that of the '||' operation. math_quaternion.h 167

Apparently, in one fragment the && operator was accidentally written instead of ||.

The code of FlightGear project (C):

static int tokMatch(struct Token* a, struct Token* b)
{
  int i, l = a->strlen;
  if(!a || !b) return 0;
  ....
}

PVS-Studio warning: V595 The 'a' pointer was utilized before it was verified against nullptr. Check lines: 478, 479. codegen.c 478

If we pass NULL as the first argument to the function, we'll get null pointer dereference, although the programmer wanted the function to return 0.

The code of WinMerge project (C++):

int TimeSizeCompare::CompareFiles(int compMethod,
                                  const DIFFITEM &di)
{
  UINT code = DIFFCODE::SAME;
  ...
  if (di.left.size != di.right.size)
  {
    code &= ~DIFFCODE::SAME;
    code = DIFFCODE::DIFF;
  }
  ...
}

PVS-Studio warning: V519 The 'code' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 79, 80. Merge timesizecompare.cpp 80

The code of ReactOS project (C++):

#define IsEqualGUID(rguid1, rguid2) \
  (!memcmp(&(rguid1), &(rguid2), sizeof(GUID)))

static int ctl2_find_guid(....)
{
  MSFT_GuidEntry *guidentry;
  ...
  if (IsEqualGUID(guidentry, guid)) return offset;
  ...
}

PVS-Studio warning: V512 A call of the 'memcmp' function will lead to underflow of the buffer 'guidentry'. oleaut32 typelib2.c 320

A pointer is written here as the first argument. As a result, the address of the pointer gets evaluated, which has no sense.

Correct variant:

if (IsEqualGUID(*guidentry, guid)) return offset;

The code of IronPython and IronRuby project (C#):

public static bool Equals(float x, float y) {
  if (x == y) {
    return !Single.IsNaN(x);
  }
  return x == y;
}

PVS-Studio warning: V3024 An odd precise comparison: x == y. Consider using a comparison with defined precision: Math.Abs(A - B) < Epsilon. FloatOps.cs 1048

It's not clear what is the point of a special check against NaN here. If the condition (x == y) is true, it means that both x and y and different from NaN, because NaN isn't equal to any other value, including itself. It seems that the check against NaN is just not necessary, and the code can be shortened to:

public static bool Equals(float x, float y) {
  return x == y;
}

The code of Mono project (C#):

public bool Equals (CounterSample other)
{
  return
    rawValue         == other.rawValue         &&
    baseValue        == other.counterFrequency &&   // <=
    counterFrequency == other.counterFrequency &&   // <=
    systemFrequency  == other.systemFrequency  &&
    timeStamp        == other.timeStamp        &&
    timeStamp100nSec == other.timeStamp100nSec &&
    counterTimeStamp == other.counterTimeStamp &&
    counterType      == other.counterType;
}

PVS-Studio warning: V3112 An abnormality within similar comparisons. It is possible that a typo is present inside the expression 'baseValue == other.counterFrequency'. System-net_4_x CounterSample.cs 139

How Do these Programs Work at all?

Looking through all the errors, it seems miraculous that all these programs generally work. Indeed, the comparison functions do a very important and responsible task in program.

There are several explanations of why these programs work despite these errors:

  1. In a lot of functions, only a part of the object is compared incorrectly. The partial comparison is enough for most of the tasks in this program.
  2. There are no situations (yet) when the function works incorrectly. For example, this applies to the functions that aren't protected from null pointers or those, where the result of the memcmp function call is placed into the variable of char type. The program is simply lucky.
  3. The reviewed comparison function is used very rarely or not used at all.
  4. Who said that the program is working? A lot of programs really do something wrong!

Recommendations

I demonstrated how many errors can be found in the comparison functions. It follows that the efficiency of these functions should be checked with unit-tests by all means.

It is really necessary to write unit-tests for the comparison operators, for Equals functions and so on.

I am quite sure that there was such an understanding among programmers before reading this article, that unit tests for such functions is extra work and they won't detect any errors anyway: the comparison functions are just so simple at the first glance... Well, now I showed the horror that can hide in them.

Code reviews and using static analysis tools would also be a great help.

Conclusion

In this article we mentioned a large amount of big-name projects that are developed by highly qualified experts. These projects are thoroughly tested using different methodologies. Still, it didn't stop PVS-Studio from finding errors in them. This shows that PVS-Studio can become a nice complement to other methodologies used to improve the quality and reliability of the code.

Getting Started with Ubuntu* Core on an Intel® IoT Gateway

$
0
0

Introduction

This article demonstrates to new users how to install Ubuntu* Core on an Intel® IoT Gateway GB-BXTB-3825. The GB-BXTB-3825 is powered by an Intel® Atom™ E3825 dual-core processor which would be ideal for industrial applications such as data generation, data aggregation, and data analysis. Ubuntu* Core is a lightweight, transactional version of Ubuntu* designed for deployments on IoT devices. Snaps are universal Linux packages that are available to install on Ubuntu* Core to work on IoT devices and more. More information on the Gateway GB-BXTB-3825 is available at http://b2b.gigabyte.com/Embedded-System/GB-BXBT-3825-rev-10#ov. You can get detailed information on the Ubuntu* Core at https://www.ubuntu.com/core.

Hardware Requirements

The hardware components used in this project are listed below:

  • An Intel® IoT Gateway: GB-BXTB-3825
  • 2 USB 2.0 or 3.0 flash drives with at least 2GB free space available
  • USB keyboard and mouse
  • A monitor with VGA or HDMI interface
  • A VGA or HDMI cable
  • A network connection with Internet access
  • An existing Linux* system is required to generate the RSA key (see Figure-1 below) and to login with SSH into the Ubuntu Core (Figure-11 and Figure-12 below).

Software Requirements

The software requirements used in this project are listed below:

Generate a Host SSH Key

The first step is to create an Ubuntu SSO account from https://login.ubuntu.com. The account is required to create the first user on an Ubuntu Core installation.

  • Click on the Personal details to fill out your information.
  • Generate an RSA key

Use an existing Linux system to generate the RSA key by running ssh-keygen-trsa on the Linux shell:

 Generate an SSH key on the Linux shell

Figure 1: Generate an SSH key on the Linux shell

Your public key is now available as .ssh/id_rsa.pub in your home folder /home/Ubuntu/.ssh/id_rsa.pub.

  • Click on the SSH keys and insert the contents of your public key /home/Ubuntu/.ssh/id_rsa.pub.

 Submitted the SSH keys successfully

Figure 2: Submitted the SSH keys successfully

 

Updating the BIOS

The Gateway should have its BIOS updated to the latest version. To check your Gateway BIOS version:

  • Go to Start -> Run -> type “msinfo32.exe” or
  • Turn on your Gateway and press F12 to enter the BIOS

Visit http://www.intel.com/content/www/us/en/support/boards-and-kits/000005850.html to download the latest BIOS version and for instructions on how to install.

Create a Live USB Ubuntu* Flash Drive

Booting from the Live USB Flash Drive

  • Connect the USB hub, keyboard, mouse and the monitor to the Gateway GB-BXTB-3825.

 Gateway GB-BXTB-3825

Figure 3: Gateway GB-BXTB-3825

 

  • Insert the Live USB Ubuntu Desktop flash drive you created earlier in to the Gateway GB-BXTB-3825.
  • Turn on your Gateway GB-BXTB-3825 and press F12 on the key board to enter the boot menu.
  • Select the USB flash drive as a boot option.

 Select boot device

Figure 4: Select boot device

  • Select "Try Ubuntu without installing”.

 Try Ubuntu without installing

Figure 5: Try Ubuntu without installing

Install Ubuntu* Core Image

  • Insert the second USB flash drive containing the Ubuntu Core image file.
  • Open a terminal and type:
xzcat /media/ubuntu/<name of the second USB flash drive>/ubuntu-core-16-amd64.img.xz | sudo dd of=/dev/sda bs=32M status=progress; sync

 Flash Ubuntu Core

Figure 6: Flash Ubuntu Core

  • Reboot the Gateway. The Gateway will reboot from the internal memory where the Ubuntu Core has been flashed.

Configure the Gateway

  • After the Gateway has rebooted, you will see a prompt to Press enter to configure.
  • Select start to configure your network. Below is an example of the network configuration.

 Configure IPv4

Figure 7: Configure IPv4

 After network configuration

Figure 8: After network configuration

  • Enter the Ubuntu One email address that was set up earlier.

 Profile setup

Figure 9: Profile setup

 Configuration complete

Figure 10: Configuration complete

First User login

  • First, add RSA identities to the authentication agent by running ssh-add on the shell.

 ssh-add command

Figure 11: ssh-add command

  • Next, login with SSH into the Ubuntu Core from a different machine on the same network. The password is not required.

 ssh into Ubuntu Core

Figure 12: ssh into Ubuntu Core

  • Set a password in case you want to login from the local console on the IOT Gateway.

 Set a password

Figure 13: Set a password

Run Hello World Snap on LocalHost

Now the Gateway is ready for the snaps. Snaps are self-contained application bundles that contain most of the libraries and runtimes needed. It is a squashFS filesystem containing your app code and a snap.yaml file.

  • Sign in to a Snap store using an Ubuntu SSO account:

 Sign in to a snap store

  • Install the Hello Snap using the snap name:

 Install hello snap

Figure 15: Install hello snap

  • Run the Hello Snap:

 Run hello snap

Figure 16: Run hello snap

Summary

We have described how to install Ubuntu* Core on an Intel IoT Gateway GB-BXTB-3825 and also how to run the Hello World Snap. Visit https://snapcraft.io/docs/build-snaps to make your own snap and enjoy the power of the Intel® IoT Gateway GB-BXTB-3825.

Key References

  • Intel® Developer Zone:

https://software.intel.com/en-us/iot/home

  • GB-BXTB-3825 Product overview:

http://b2b.gigabyte.com/Embedded-System/GB-BXBT-3825-rev-10#ov

  • GB-BXTB-3825 Product

https://help.ubuntu.com/community/SSH/OpenSSH/Keys

  • Ubuntu Core

https://www.ubuntu.com/core

  • Generate an SSH Key

https://help.ubuntu.com/community/SSH/OpenSSH/Keys

  • Create a bootable USB stick on Windows*

https://www.ubuntu.com/download/desktop/create-a-usb-stick-on-windows

  • Download Rufus USB Installer

https://rufus.akeo.ie

  • Get started with the snap command

https://developer.ubuntu.com/core/get-started/intel-nuc

  • Build snaps

https://snapcraft.io/docs/build-snaps

 

About the Author

Nancy Le is a software engineer at Intel Corporation in the Software and Services Group working on Intel Atom® processor enabling for Intel® IoT projects.

 

 

 

 

Making Smart Systems Smarter

$
0
0

The Internet of Things is growing exponentially and shows no signs of stopping. We’ve all heard the statistics. By 2020, there will be billions of connected devices. And these devices are generating explosive volumes of data. The good news is that IoT devices are transforming the way we do business and helping to create a safer, more efficient, more innovative future. The bad news? If all that data has to be transported to the cloud for processing and analyzing, networks will be massively overwhelmed — leading us to a world of delayed results. 

But not bad news for long. Smart, connected “things” are getting smarter. And a more intelligent edge is becoming capable of doing more complex analytics. In fact, IDC predicts “by 2019, at least 40 percent of IoT-created data will be stored, processed, analyzed, and acted upon close to or at the edge of the network associated drivers.”

Think of a factory using smart devices to monitor the work environment and send notifications if conditions reach unsafe levels. The devices can sense the issue and process the data—enabling time-critical alerts so workers can be evacuated safely. Think of an oil or mining company using sensors and edge computing to monitor conditions and control heavy equipment to automate and optimize operations in remote locations. These are just two examples of how an IoT system with more compute power at the edge can speed the movement of data from insight to action.

Intel is driving smarter devices and a more intelligent edge with cloud and edge technologies that drive greater business value, edge analytics, deep learning and machine learning capabilities.  

To further these efforts, we have created a joint reference architecture with Amazon Web Services (AWS)* and are launching an Enterprise IoT Developer Kit. The architecture incorporates AWS Greengrass software, which works seamlessly with the Intel® IoT Platform. With Greengrass, Intel® devices can ingest, process, and store data locally and make local decisions, paired with leading cloud-based capabilities.   

The developer kit provides integration of sensors and the middleware protocol stack, shortening time-to-market from prototyping to deployment. The kit includes: Intel® IoT Gateway Technology, AWS* IoT and Greengrass-specific plugins, development boards and starter kits, IDEs to support a variety of programming languages, libraries to support I/O and sensor interactions, documentation, and code samples.

Intel has been implementing the reference architecture across their ecosystem, working with IoT Equipment Builders for validation and testing to ensure compatibility. There are already a number of Intel-based IoT Gateways validated for Greengrass, provided by leading IoT Equipment Builders, who are members of the IoT Solutions Alliance. With the backing of an extended IoT community, these and other IoT solutions are driving real-time insights to help businesses increase revenue, cut costs, and improve business outcomes. 

Smarter things that are part of a more intelligent edge will fuel the growth of the IoT and its capability to bring meaning to data and benefits to business. To learn more, visit intel.com/iot/aws.


1IDC FutureScape: Worldwide Internet of Things 2017 Predictions, November 2016.

What's New? Intel® Threading Building Blocks 2017 Update 7

$
0
0

The updated version contains a new bug fix when compared to the previous  Intel® Threading Building Blocks (Intel® TBB) 2017 Update 6 release. Information about new features of previous release you can find under the following link.

Added functionality:

  • In the huge pages mode, the memory allocator now is also able to use transparent huge pages.

Preview Features:

  • Added support for Intel TBB integration into CMake-aware projects, with valuable guidance and feedback provided by Brad King (Kitware).

Bugs fixed:

  • Fixed scalable_allocation_command(TBBMALLOC_CLEAN_ALL_BUFFERS, 0) to process memory left after exited threads.

Intel TBB 2017 Update 7 is open source only release, you can download it from https://github.com/01org/tbb/releases.

 


Intel® Advisor 2017 Update 4: What’s New

$
0
0

 

We’re pleased to announce a new version of the Vectorization Assistant tool: Intel® Advisor 2017 Update 4. For details about download, terms and conditions, please refer to the Intel® Parallel Studio 2017 program site.

Below are highlights of the new functionality in Intel® Advisor 2017 Update 4:

Bug fixes

Get Intel® Advisor and more information

Visit the product site, where you can find videos and tutorials. Register for Intel® Parallel Studio XE 2017 to download the whole bundle, including Intel® Advisor 2017 update 4.

How to Use Cache Monitoring Technology in OpenStack*

$
0
0

Introduction

With an increasing number of workloads running simultaneously on a system, there is more pressure on shared resources such as the CPU, cache, network bandwidth, and memory. While this reduces workload performance, if one or more of the workloads is bursty in nature it also reduces performance determinism. An interfering workload is called a noisy neighbor, and for the purposes of this discussion a workload could be any software application, a container, or even a virtual machine (VM).

Intel® Resource Director Technology (Intel® RDT) provides hardware support to monitor and manage shared resources, such as the last level cache (LLC) (also called the L3 cache), and memory bandwidth. In conjunction with software support, starting with the operating system and going up the solution stack, this functionality is being made available to monitor and manage shared resources to isolate workloads and improve determinism. In particular, the cache monitoring technology (CMT) aspect of Intel RDT provides last-level cache usage information for a workload.

OpenStack* is an open source cloud operating system that controls datacenter resources, namely compute, storage, and networking. Users and administrators can access the resources through a web interface or RESTful API calls. For the purposes of this document, we assume that the reader has some knowledge of OpenStack, either as an operator/deployer, or as a developer.

Let us explore how to enable and use CMT, in the context of an OpenStack cloud, to detect cache-related workload interference and take remedial action(s).

Note 1: Readers of this article should have basic understanding of OpenStack and its deployment and configuration.

Note 2: All of the configurations and examples are based on the OpenStack Newton* release version (released in October 2016) and the Gnocchi* v3.0 release.

Enabling CMT in OpenStack*

To leverage CMT in OpenStack requires touching the Nova*, Ceilometer*, and optionally the Gnocchi and Aodh* projects. The Nova project concerns itself with scheduling and managing workloads on the compute hosts. Ceilometer and Gnocchi pertain to telemetry. The Ceilometer agent runs on the compute hosts, gathers configured items of telemetry, and pushes them out for storage and future retrieval. The actual telemetry data could be saved in Ceilometer’s own database or the Gnocchi time series database with indices. The latter is superior, in both storage efficiency and retrieval speed. OpenStack Aodh supports defining rule-action pairs, such as whether some telemetry crosses a threshold and, if so, whether to emit an alarm. Alarms in turn could trigger some kind of operator intervention.

Enabling CMT in Nova*

OpenStack Nova provides access to the compute resources via a RESTful API and a web dashboard. To enable the CMT feature in Nova, the following preconditions have to be met:

  • The compute node hardware must support the CMT feature. The following CPUs support CMT (but are not limited to): Intel® Xeon® processor E5 v3 and Intel Xeon processor E5 v4 families. Please verify that the CPU specification supports CMT.
  • The libvirt version installed on Nova compute nodes is version 2.0.0 or greater.
  • The hypervisor running on the Nova compute host is a kernel-based virtual machine.

If all of the above preconditions are satisfied, and Nova is currently running, edit the libvirt section of the Nova configuration file (by default it is /etc/nova/nova.conf):

[libvirt]
virt_type = kvm
enabled_perf_events = cmt

After saving the above modifications, restart the Nova compute service.;

Openstack-nova-compute is a service on each compute host.

On Ubuntu* and CentOS* 6.5 hosts, run the following commands to restart the Nova compute service:

# service openstack-nova-compute restart
# service openstack-nova-compute status

On CentOS 7 and Fedora* 20 hosts, run the following commands instead to restart the Nova compute service:

# systemctl restart openstack-nova-compute
# systemctl status openstack-nova-compute

Once Nova is restarted, any new VMs launched by Nova will have the CMT feature enabled.

If devstack is being used instead to install a fresh OpenStack environment, add the following to the devstack local.conf file:

[[post-config|$NOVA_CONF]]
[libvirt]
virt_type = kvm
enabled_perf_events = cmt, mbml, mbmt

After saving the above configuration, run devstack to start the installation.

Enabling CMT in Ceilometer*

Ceilometer is part of the OpenStack Telemetry project whose mission is to:

  • Reliably collect utilization data from each host and for the VMs running on those hosts.
  • Persist the data for subsequent retrieval and analysis.
  • Trigger actions when defined criteria are met.

To get the last-level cache usage of a running VM, Ceilometer must be installed, configured to collect the cpu_l3_cache metric, and be running. Ceilometer defaults to collecting the metric. The cpu_l3_cache metric is collected by the Ceilometer agent running on the compute host by periodically polling for VM utilization metrics on the host.

If devstack is being used to install Ceilometer along with other OpenStack services and components, add the following in the devstack local.conf file:

[[local|localrc]]
enable_plugin ceilometer git://git.openstack.org/openstack/ceilometer
enable_plugin aodh git://git.openstack.org/openstack/aodh

After saving the above configuration, run devstack to start the installation. This will install Ceilometer as well as Aodh (OpenStack alarming service) in addition to other OpenStack services and components.

Storing the CMT Metrics

There are two options to save telemetry data; namely in Ceilometer’s own backend database or in Gnocchi’s (also a member of the OpenStack Telemetry project) database. Gnocchi provides a time-series database with a resource indexing service, which is vastly superior to the Ceilometer native storage with respect to performance at scale, better disk utilization, and faster data retrieval. We recommend installing Gnocchi and configuring storage with the same. To do so using devstack, modify the following devstack local.conf file as follows:

[[local|localrc]]
enable_plugin ceilometer git://git.openstack.org/openstack/ceilometer
CEILOMETER_BACKEND=gnocchi
enable_plugin aodh git://git.openstack.org/openstack/aodh
enable_plugin gnocchi git://git.openstack.org/openstack/gnocchi

After saving the above configuration, run devstack to start the installation.

Refer to Gnocchi documentation for information on other Gnocchi installation methods.

After installing Gnocchi and Ceilometer, confirm that the following configuration settings are in place:

In the Ceilometer configuration file (by default it is /etc/ceilometer/ceilometer.conf), make sure the options are listed as follows:

[DEFAULT]
meter_dispatchers = gnocchi
[dispatcher_gnocchi]
filter_service_activity = False
archive_policy = low
url = <url to the Gnocchi API endpoint>

In the Gnocchi dispatcher configuration file (by default it is /etc/ceilometer/gnocchi_resources.yaml), make sure that the cpu_l3_cache metric is added into the resource type instance’s metrics list:

… …
  - resource_type: instance
    metrics:
      - 'instance'
      - 'memory'
      - 'memory.usage'
      - 'memory.resident'
      - 'vcpus'
      - 'cpu'
      - 'cpu_l3_cache'
… …

If any modifications are made to the above configuration files, you must restart the Ceilometer collector so that the new configurations take effect.

Verify Things are Working

To verify that all of the above are working, test as follows:

  1. Create a new VM.

    $ openstack server create --flavor m1.tiny --image cirros-0.3.4-x86_64-uec abc

  2. Confirm that the VM has been created successfully.

    $ openstack server list

    ID

    Name

    Status

    Networks

    Image Name

    7e38a89b-c829-4fb9-b44a-35090fbc0866

    abc

    ACTIVE

    private=10.0.0.3

    cirros-0.3.4-x86_64-uec

  3. Wait for some time to allow the Ceilometer agent to collect the cpu_l3_cache metrics. The wait time is determined by the related pipeline defined in the /etc/ceilometer/pipeline.yaml file.
  4. Check to see if the related metrics are collected and stored.
    1. If the metric is stored in Ceilometer’s own database backend, use the following command:

      ID

      Resource ID

      Name

      Type

      Volume

      Unit

      Timestamp

      f42e275a-b36a-11e6-96b2-525400e9f0eb

      7e38a89b-c829-4fb9-b44a-35090fbc0866

      cpu_l3_cache

      gauge

      270336.0

      B

      2016-12-08T23:57:37.535615

      8e872286-b369-11e6-96b2-525400e9f0eb

      7e38a89b-c829-4fb9-b44a-35090fbc0866

      cpu_l3_cache

      gauge

      450560.0

      B

      2016-12-08T23:47:37.505369

      28e57758-b368-11e6-96b2-525400e9f0eb

      7e38a89b-c829-4fb9-b44a-35090fbc0866

      cpu_l3_cache

      gauge

      270336.0

      B

      2016-12-08T23:37:37.536424

      …...

      …...

      …...

      …...

      …...

      …...

      …...

    2. However, if the metric is stored in Gnocchi, access it as follows:

      $ gnocchi measures show --resource-id 9184470a-594e-4a46-a124-fa3aaaf412dc cpu_l3_cache --aggregation mean

      Timestamp

      Granularity

      Value

      2016-12-09T00:00:00+00:00

      86400.0

      282350.933333

      2016-12-09T01:00:00+00:00

      3600.0

      216268.8

      2016-12-09T01:45:00+00:00

      300.0

      180224.0

      2016-12-09T01:55:00+00:00

      300.0

      180224.0

      … ...

      … ...

      … ...

Using CMT in OpenStack

A noisy neighbor in the OpenStack environment could be a VM consuming resources in a manner that adversely affects one or more different VMs on the same compute node. Whether because of a lack of knowledge of workload characteristics, appropriate information during Nova scheduling, or a change in the workload characteristics (because of a spike in usage or a virus or other), a noisy situation may occur on a host. The cloud admin might want to detect and take some action, such as live migrating the greedy workload or terminating it. The OpenStack Aodh project) enables detecting scenarios and alerting to their existence using condition-action pairs. An Aodh rule that monitors VM cache usage crossing some threshold would automate detecting of noisy neighbor scenarios.

Below, we illustrate setting up an Aodh rule to detect noisy neighbors. The actual rule depends upon whether the CMT telemetry data is stored. We first cover storage in the Ceilometer database and then in the Gnocchi time series database.

Metrics Stored in Ceilometer Database

Below, we define, using the Aodh command-line utility, a threshold CMT metrics rule:

$ aodh --debug alarm create --name cpu_l3_cache -t threshold --alarm-action "log://" --repeat-actions True --comparison-operator "gt" --threshold 180224 --meter-name cpu_l3_cache --period 600 --statistic avg

Field

Value

alarm_actions

[u'log://']

alarm_id

e3673d39-90ed-4455-80f1-fd7e06e1f2b8

comparison_operator

gt

description

Alarm when cpu_l3_cache is gt a avg of 180224 over 600 seconds

enabled

True

evaluation_periods

1

exclude_outliers

False

insufficient_data_actions

[]

meter_name

cpu_l3_cache

name

cpu_l3_cache

ok_actions

[]

period

600

project_id

f1730972dd484b94b3b943d93f3ee856

repeat_actions

True

query

 

severity

low

state

insufficient data

state_timestamp

2016-12-08T23:59:05.712994

statistic

avg

threshold

180224

time_constraints

[]

timestamp

2016-12-08T23:59:05.712994

type

threshold

user_id

cfcd1ea48a1046b192dbd3f5af11290e

This creates an alarm rule named cpu_l3_cache that is triggered if, and only if, within a sliding window of 10 minutes (600 seconds), the VM’s average cpu_l3_cache metric is greater than 180224. If the alarm is triggered, it will be logged in the Aodh alarm notifier agent’s log. Alternately, instead of just logging the alarm event, a notifier may be used to push a notification to one or more configured endpoints. For example, we could use the http notifier by providing "http://<endpoint ip>:<endpoint port>" as the alarm-action parameter.

Metrics Stored in Gnocchi*

If the metrics are stored in Gnocchi, an Aodh alarm could be created through a gnocchi_resources_threshold rule such as the following, using the Aodh command-line utility:

$ aodh --debug alarm create -t gnocchi_resources_threshold --name test1 --alarm-action "log://alarm" --repeat-actions True --metric cpu_l3_cache --threshold 100000 --resource-id 9184470a-594e-4a46-a124-fa3aaaf412dc --aggregation-method mean --resource-type instance --granularity 300 --comparison-operator 'gt'

Field

Value

aggregation_method

mean

alarm_actions

[u'log://alarm']

alarm_id

71f48ee1-b92f-4982-92e4-4c520649a8e0

comparison_operator

gt

description

gnocchi_resources_threshold alarm rule

enabled

True

evaluation_periods

1

granularity

300

insufficient_data_actions

[]

metric

cpu_l3_cache

name

test1

ok_actions

[]

period

600

project_id

543aa2e8e17449149d5c101c55675005

repeat_actions

True

resource_id

9184470a-594e-4a46-a124-fa3aaaf412dc

resource_type

instance

state

insufficient data

state_timestamp

2016-12-09T05:57:07.089530

threshold

100000

time_constraints

[]

timestamp

2016-12-09T05:57:07.089530

type

gnocchi_resources_threshold

user_id

ca859810b379425085756faf6fd04ded

This creates an alarm named test1 if, and only if, within a sliding 10-minute window (600 seconds), the VM 9184470a-594e-4a46-a124-fa3aaaf412dc registers an average cpu_l3_cache metric greater than 180224. If triggered, an alarm is logged to the Aodh alarm notifier agent’s log output. Instead of the command-line utility the Aodh RESTful API could be used to define alarms; refer to http://docs.openstack.org/developer/aodh/webapi/v2.html for details.

While Gnocchi v3.0 is limited in its resource querying capabilities in comprehending metric type and thresholds, such enhancements are expected in future releases.

More About Intel® Resource Director Technology (Intel® RDT)

The Intel RDT family comprises, beyond CMT, other monitoring and resource allocation technologies. Those that will soon be available are:

  • Cache Allocation Technology (CAT) enables allocation of cache to workloads, either in exclusive or shared mode, to ensure performance despite co-resident (running on the same host) workloads. For instance, more cache can be allocated to a high-priority task that has a larger working set or, conversely, restricting cache usage for a streaming application that has a lower priority so that it does not interfere with higher priority tasks.
  • Memory Bandwidth Monitoring (MBM), along the lines of CMT, provides memory usage information for workloads.
  • Code Data Prioritization (CDP) enables separate control over code and data placement in the last-level cache.

To learn more visit http://www.intel.com/content/www/us/en/architecture-and-technology/resource-director-technology.html.

In conclusion, we hope the above provides you with adequate information to start using CMT in an OpenStack cloud to gain deeper insights into workload characteristics to positively influence performance.

Exploring the HPS and FPGA onboard the Terasic DE10-Nano

$
0
0

Introduction:

The Terasic DE-10 Nano is a development kit that contains a Cyclone* V device.  The Cyclone V contains a Hard Processor System (HPS) and field-programmable gate array (FPGA) with a wealth of peripherals onboard for creating some interesting applications.  One of the most basic things to accomplish with this system is to control the LEDs that are physically connected to the FPGA.  This tutorial will discuss four different methods for controlling the LEDs using the command line, memory mapped IO, schematic, and Verilog HDL.  Whether you are an application developer, firmware engineer, hardware engineer, or enthusiast, there is a method suited for you.

 

Prerequisites:

There are a wealth of datasheets, user guides, tools, and other information available for the DE-10 Nano.  It is encouraged to review this documentation to get a deeper understanding of the system.  For this tutorial, please download and install the following first:

01:  Intel® Quartus® Prime Software Suite Lite Edition for Cyclone V - http://dl.altera.com/?edition=lite

02:  Install EDS with DS-5 - http://dl.altera.com/soceds/

03:  Install Putty (Windows* Users) - http://www.putty.org/

04:  Install WinScp (Windows Users) - https://winscp.net/eng/download.php

05:  Install the RNDIS Ethernet over USB driver (Windows Users) – See Terasic DE10 Nano Quick Start Guide Section 3

06:  Download  DE-10 Nano Resources - http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=205&No=1046&PartNo=4

 

Method #1 - Command Line:

Out of the box, the DE-10 Nano HPS is pre-configured to boot a Linux* image and the FPGA is pre-configured with the Golden Hardware Reference Design (GHRD).  This means you have a complete system and can get started exploring right away by simply applying power to the board.  The most basic method to control an LED using the DE-10 Nano HPS is with the file system.  This method lends itself well to the scripters out there that want to do something basic and work at the filesystem level.  This can be easily illustrated using the serial terminal.  To begin, perform the following:

01:  Connect a Mini-B USB cable from the host to the DE10 Nano USB UART (Right Side of board)

02:  Open a serial terminal program

03:  Connect using a 115200 baud rate

04:  Login as root, no password is needed

05:  Turn on the LED

               echo 1 >  /sys/class/leds/fpga_led0/brightness

06:  Turn off the LED

               echo 0 >  /sys/class/leds/fpga_led0/brightness

 

Method #2 – C Based Application:

Another method to control the LEDs using the HPS, is to go lower level and develop a Linux application that accesses the memory mapped regions in SDRAM exposed by the FPGA that control the LEDs.  The HPS can access this region using the Lightweight HPS2FPGA AXI Bridge (LWFPGASLAVES) that connects to the Parallel IO (LED_PIO) area.  The C based application will map this region into the user application space, toggle all 8 LEDs every 500ms for a few times, unmap the region, and exit.  We will develop the application using the Eclipse DS-5 IDE.  To begin, perform the following:

01:  Open Eclipse DS-5

02:  Create a New Project

               02a:  File->New->C Project->Hello World Project

               02b:  Enter a project Name

               02c:  Select GCC 4.x [arm-linux-gnueabihf) Toolchain

               02d:  Click Finish

03:  Delete the generated Hello World code

04:  Add Preprocessor Includes & Defines

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#define ALT_LWFPGASLVS_OFST 0xFF200000
#define LED_PIO_BASE             0x3000
#define LED_PIO_SPAN            0x10

05: Add main() function

 int main(void)
 {
           unsigned long *led_pio;
           int fd;
           int i;

           fd = open("/dev/mem", (O_RDWR | O_SYNC));


           //Map LED_PIO Physical Address to Virtual Address Space
           led_pio = mmap( NULL, LED_PIO_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, (ALT_LWFPGASLVS_OFST + LED_PIO_BASE) );

           //Toggle all LEDs every 500ms a few times
           for (i=0; i < 10; i++)
           {
                *led_pio ^= 0xFF; //Bit0=LED0 … Bit7=LED7
                usleep(1000*500);
           }


           //Unmap
           munmap(led_pio, LED_PIO_SPAN);

           close(fd);
           return(0);
 }

   

06:  Build the Project

               Project->Build Project

07:  Test out the application

               06a:  Connect a micro USB cable from the host to the DE10 Nano USB OTG Port

               06b:  Use scp to transfer the application to the DE10 Nano at root@192.168.7.1

               06c:  Run the application from the serial terminal ./<applicationName>

 

Methods #3 & #4 - Schematic and Verilog HDL:

So far we have been controlling the LEDs connected to the FPGA from the HPS using the command line and a C based application.  Now let’s discuss controlling the LEDs directly using just the FPGA logic.  In this design, we will turn on/off 2 LEDs when a pushbutton is pressed/released respectively.  It should be noted that the pushbutton is pulled up and the LEDs are active high so an inverter is used to get the desired behavior when the button is pressed/released.  We will use a schematic based approach to create the logic to control the first LED and a Verilog HDL approach to create the similar logic to control the second LED.  We will create the design using the Intel® Quartus® Prime Software Suite Lite Edition software.  To begin the project, perform the following:

01:  Open Quartus Prime Lite

02:  Create a New Project

               02a:  File->New->New Quartus Prime Project->Next

               02b:  Enter Project Name->Next->Empty Project

               02c:  Click Next                      

               02c:  Name Filter->5CSEBA6U23I7->Finish

03:  Create a New Schematic File

               03a:  File->New->Block Diagram/Schematic File

04:  Add LED Output Pins

               04a:  Right Click->Insert Symbol->primitives->pin->output

               04b:  Right Click->Insert Symbol->primitives->pin->output

               04c:  Right Click on output pin->Properties->Name=led_0

               04d:  Right Click on output pin->Properties->Name=led_1

05:  Add Push Button Input Pin

               05a:  Right Click->Insert Symbol->primitives->pin->input

               05b:  Right Click on input pin->Properties->Name=pushButton

06:  Add Inverter

                06a:  Right Click->Insert Symbol->primitives->logic->not

07:  Connect Everything Up

               07a:  Connect pushButton to Inverter Input

               07b:  Connect Inverter Output to led_0

08:  Create a New Verilog HDL File

               08a:  File->New->Verilog HDL File

               08b:  Enter Verilog Code     

module inverter (

           input      in,
           output     out
     );

     assign out = !in;

endmodule 

    08c:  Save File

               08d:  Update Symbols

                              File->Create/Update->Create Symbols From Current File

               08e:  Add Verilog Module to Top Level Schematic

                              Right Click->Insert Symbol->inverter->Click Ok

               

               08f:  Connect pushButton Input to Inverter Input

               08g:  Connect Inverter Output to led1 Output Pin

               

              

09:  Assign Inputs and Outputs to Physical FPGA Pins

               09a:  Processing->Start->Start Analysis & Elaboration

               09b:  Assignments->Pin Planner

                              led0->Location=PIN_W15, I/O Standard=3.3-V LVTTL

                              led1->Location=PIN_AA24, I/O Standard=3.3-V LVTTL

                              pushButton->Location=PIN_AH17

10:  Compile Project

               10a:  Start->Start Compilation

11:  Program the FPGA

               11a:  Connect mini USB cable to JTAG USB Blaster port (near HDMI connector and Blue LED)

               11b:  Click Tools->Programmer

               11c:  Click Hardware Setup->Currently Selected Hardware->DE-SoC

               11d:  Click AutoDetect->5CSEBA6

               11e:  Click on 5CSEBA6U23 Chip Picture

               11f:  Click Change File-><project directory>\output_files\yourFile.sof

               11g:  Click Program/Configure checkbox

               11h:  Click Start Button

12:  Test out the design

               12a:  Push and hold the right pushbutton and led0 and led1 will turn on

12b:  Release the pushbutton and the LEDs will turn off

 

Summary:

The DE-10 Nano has a lot to offer the engineer from its capabilities, variety of tools, programming methods, and documentation.  This tutorial showed four different methods for controlling the LEDs that utilized the HPS and FPGA using the available tools.  You can take all of these concepts to the next level when you begin your next project with the DE-10 Nano.

 

About the Author:

Mike Rylee is a Software Engineer at Intel Corporation with a background in developing embedded systems and apps for Android*, Windows*, iOS*, and Mac*.  He currently works on Internet of Things projects.          

              

Notices:

No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document.

Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade.

This document contains information on products, services and/or processes in development. All information provided here is subject to change without notice. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps.

The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request.

Copies of documents which have an order number and are referenced in this document may be obtained by calling 1-800-548-4725 or by visiting www.intel.com/design/literature.htm.

Intel, the Intel logo, and Intel RealSense are trademarks of Intel Corporation in the U.S. and/or other countries.

*Other names and brands may be claimed as the property of others

**This sample source code is released under the Intel Sample Source Code License Agreement

© 2017 Intel Corporation.            

Fast Computation of Adler32 Checksums

$
0
0

Abstract

Adler32 is a common checksum used for checking the integrity of data in applications such as zlib*, a popular compression library. It is designed to be fast to execute in software, but in this paper we present a method to compute it with significantly better performance than the previous implementations. We show how the vector processing capabilities of Intel® Architecture Processors can be exploited to efficiently compute the Adler32 checksum.

Introduction

The Adler32 checksum (https://en.wikipedia.org/wiki/Adler-32) is similar to the Fletcher checksum, but it is designed to catch certain differences that Fletcher is not able to catch. It is used, among other places, in the zlib data compression library (https://en.wikipedia.org/wiki/Zlib), a popular general-purpose compression library.

While scalar implementations of Adler32 can achieve reasonable performance, this paper presents a way to further improve the performance by using the vector processing feature of Intel processors. This is an extension of the method we used to speed up the Fletcher checksum as described in (https://software.intel.com/en-us/articles/fast-computation-of-fletcher-checksums).

Implementation

If the input stream is considered to be an array of bytes (data), the checksum essentially consists of two 16-bit words (A and B), and the checksum can be defined as:

for (i=0; i<end; i++) {
     A = (A + data[i]) % 65521;
     B = (B + A) % 65521;
}

Doing the modulo operation after every addition is expensive. A well-known way to speed this up is to do the addition using larger variables (for example, 32-bit dwords), and then to perform the modulo only when the variables are about to risk overflowing, for example:

for (i=0; i<5552; i++) {
     A = (A + data[i]);
     B = (B + A);
}
A = A % 65521;
B = B % 65521;

The reason that up to 5552 bytes can be processed before needing to do the modulo is that if A and B are initially 65520 and the data is all 0xFF (255), after processing 5552 bytes, B (the larger of the two) will be 0xFFFBC598. But if one processes 5553 such bytes, the result would be greater than 232.

Within that loop, the calculation looks the same as in Fletcher, so the same approach can be used to vectorize the calculation. In this case, the body of the main loop would be an unrolled version of:

     pmovzxbd xdata0, [data]    ; Loads byte data into dword lanes
     paddd xa, xdata0
     paddd xb, xa

One can see that this looks essentially identical to what one would do with scalar code, except that it is operating on vector registers and, depending on the hardware generation, could be processing 4, 8, or 16 bytes in parallel.

If “a[i]” represents the i’th lane of vector register “a” and N is the number of lanes, we can (as shown in the earlier paper) calculate the actual sums by:

The sums can be done using a series of horizontal adds (PHADDD), and the scaling can be done with PMULLD.

In pseudo-code, if the main loop is operating on eight lanes (either with eight lanes in one register or four lanes unrolled by a factor of two), this might look like:

While (size != 0) {
     s = min(size, 5222)
     end = data + s – 7
     while (data < end) {
           compute vector sum
           data += 8
     }
     end += 7
     if (0 == (s & 7)) {
           size -= s;
           reduce from vector to scalar sum
           compute modulo
           continue while loop
     }
     // process final 1…7 bytes
     Reduce from vector to scalar sum
     Do final adds in scalar loop
     Compute modulo
}

Performance

The following graph compares the cycles as a function of input buffer size for an optimized scalar implementation, and for both a Streaming SIMD Extension and Intel® Advanced Vector Extensions 2 (Intel® AVX2) based parallel version, as described in this paper.

One can clearly see that the vector versions have a significantly better performance than an optimized scalar one. This is true for all but the smallest buffers.

An Intel® Advanced Vector Extensions 512 version was not tested, but it should perform significantly faster than the Intel AVX2 version.

Versions of this code are in the process of being integrated and released as part of the Intel® Intelligent Storage Acceleration Library (https://software.intel.com/en-us/storage/ISA-L).

Conclusion

This paper illustrated a method for improved Adler32 checksum performance. By leveraging architectural features such as SIMD in the processors and combining innovative software techniques, large performance gains are possible.

Author

Jim Guilford is an architect in the Intel Data Center Group, specializing in software and hardware features relating to cryptography and compression.

Mathematical Concepts and Principles of Naive Bayes

$
0
0

Simplicity is the ultimate sophistication.
—Leonardo Da Vinci

Image of handwritten mathematical equations and relative annotation

With time, machine learning algorithms are becoming increasingly complex. This, in most cases, is increasing accuracy at the expense of higher training-time requirements. Fast-training algorithms that deliver decent accuracy are also available. These types of algorithms are generally based on simple mathematical concepts and principles. Today, we’ll have a look at a similar machine-learning classification algorithm, naive Bayes. It is an extremely simple, probabilistic classification algorithm which, astonishingly, achieves decent accuracy in many scenarios.

Naive Bayes Algorithm

 On a red background, top left quarter of a man&#039;s face stares out at viewer. A mathematical equation in white text is superimposed

In machine learning, naive Bayes classifiers are simple, probabilistic classifiers that use Bayes’ Theorem. Naive Bayes has strong (naive), independence assumptions between features. In simple terms, a naive Bayes classifier assumes that the presence of a particular feature in a class is unrelated to the presence of any other feature. For example, a ball may be considered a soccer ball if it is hard, round, and about seven inches in diameter. Even if these features depend on each other or upon the existence of the other features, naive Bayes believes that all of these properties independently contribute to the probability that this ball is a soccer ball. This is why it is known as naive.

Naive Bayes models are easy to build. They are also very useful for very large datasets. Although, naive Bayes models are simple, they are known to outperform even the most highly sophisticated classification models. Because they also require a relatively short training time, they make a good alternative for use in classification problems.

Mathematics Behind Naive Bayes

Bayes Theorem provides a way of calculating posterior probability P(c|x) from P(c), P(x), and P(x|c). Consider the following equation:

Image of a mathematical equation

Here,

  • P(c|x): posterior probability ofclass(c,target) givenpredictor(x,attributes). This represents the probability of c being true, provided x is true.
  • P(c): is the prior probability ofclass. This is the observed probability of class out of all the observations.
  • P(x|c): is the likelihood which is the probability ofpredictor-givenclass. This represents the probability of x being true, provided x is true.
  • P(x): is the prior probability ofpredictor. This is the observed probability of predictor out of all the observations.

Let’s better understand this with the help of a simple example. Consider a well-shuffled deck of playing cards. A card is picked from that deck at random. The objective is to find the probability of a King card, given that the card picked is red in color.

Here,

     P(King | Red Card) = ?

We’ll use,

     P(King | Red Card) = P(Red Card | King) x P(King) / P(Red Card)

So,

     P (Red Card | King) = Probability of getting a Red card given that the card chosen is King = 2 Red Kings / 4 Total Kings = ½

     P (King) = Probability that the chosen card is a King = 4 Kings / 52 Total Cards = 1 / 13

     (Red Card) = Probability that the chosen card is red = 13 Red cards / 52 Total Cards = 1/ 4

Hence, finding the posterior probability of randomly choosing a King given a Red card is:

     P (King | Red Card) = (1 / 2) x (1 / 13) / (1 / 4) = 2 / 13 or 0.153

Understanding Naive Bayes with an Example

Let’s understand naive Bayes with one more example—to predict the weather based on three predictors: humidity, temperature and wind speed. The training data is the following:

HumidityTemperature Wind Speed Weather
HumidHotFastSunny
HumidHotFastSunny
HumidHotSlowSunny
Not HumidColdFastSunny
Not HumidHotSlowRainy
Not HumidColdFastRainy
HumidHotSlowRainy
HumidColdSlowRainy

We’ll use naive Bayes to predict the weather for the following test observation:

Humidity %Temperature (C)Wind Speed (Km/h)Weather
HumidColdFast?

We have to determine which posterior is greater, sunny or rainy. For the classification Sunny, the posterior is given by:

     Posterior( Sunny) = (P(Sunny) x P(Humid / Sunny) x P(Cold / Sunny) x   P(Fast / Sunny)) / evidence

Similarly, for the classification Rainy, the posterior is given by:

     Posterior( Rainy) = (P(Rainy) x P(Humid / Rainy) x P(Cold / Rainy) x  P(Fast / Rainy)) / evidence

Where,

     evidence = [ P(Sunny) x p(Humid / Sunny) x p(Cold / Sunny) x P(Fast / Sunny) ] + [ (P(Rainy) x P(Humid / Rainy) x P(Cold / Rainy) x P(Fast / Rainy) ) ]

Here,

     P(Sunny) = 0.5
     P(Rainy) = 0.5
     P(Humid/ Sunny) = 0.75
     P(Cold/ Sunny) = 0.25
     P(Fast/ Sunny) = 0.75
     P(Humid/ Sunny) = 0.25
     P(Cold/ Sunny) = 0.75
     P(Fast/ Sunny) = 0.25

Therefore, evidence = 0.703 + 0.023 = 0.726.

     Posterior (Sunny) = 0.968
     Posterior (Rainy) = 0.032

Since the posterior numerator is greater in the Sunny case, we predict the sample is Sunny.

Applications of Naive Bayes

Naive Bayes classifiers can be trained very efficiently in a supervised learning setting. In many practical applications, parameter estimation for naive Bayes models uses the method of maximum likelihood. Despite their naive design and apparently oversimplified assumptions, naive Bayes classifiers have worked quite well in many complex real-world situations.

  • Recommendation System: Naive Bayes classifiers are used in various inferencing systems for making certain recommendations to users out of a list of possible options.
  • Real-Time Prediction: Naive Bayes is a fast algorithm, which makes it an ideal fit for making predictions in real time.
  • Multiclass Prediction: This algorithm is also well-known for its multiclass prediction feature. Here, we can predict the probability of multiple classes of the target variable.
  • Sentiment Analysis: Naive Bayes is used in sentiment analysis on social networking datasets like Twitter* and Facebook* to identify positive and negative customer sentiments.
  • Text Classification: Naive Bayes classifiers are frequently used in text classification and provide a high success rate, as compared to other algorithms.
  • Spam Filtering: Naive Bayes is widely used inspam filtering for identifying spam email.

Why is Naive Bayes so Efficient?

An interesting point about naive Bayes is that even when the independence assumption is violated and there are clear, known relationships between attributes, it works decently anyway. There are two reasons that make naive Bayes a very efficient algorithm for classification problems.

  1. Performance: The naive Bayes algorithm gives useful performances despite having correlated variables in the dataset, even though it has a basic assumption of independence among features. The reason for this is that in a given dataset, two attributes may depend on each other, but the dependence may distribute evenly in each of the classes. In this case, the conditional independence assumption of naive Bayes is violated, but it is still the optimal classifier. Further, what eventually affects the classification is the combination of dependencies among all attributes. If we just look at two attributes, there may exist strong dependence between them that affects the classification. When the dependencies among all attributes work together, however, they may cancel each other out and no longer affect the classification. Therefore, we argue that it is the distribution of dependencies among all attributes over classes that affects the classification of naive Bayes, not merely the dependencies themselves.
  2. Speed: The main cause for the fast speed of naive Bayes training is that it converges toward its asymptotic accuracy at a different rate than other methods, like logistic regression, support vector machines, and so on. Naive Bayes parameter estimates converge toward their asymptotic values in order of log(n) examples, where n is number of dimensions. In contrast, logistic regression parameter estimates converge more slowly, requiring order n examples. It is also observed that in several datasets logistic regression outperforms naive Bayes when many training examples are available in abundance, but naive Bayes outperforms logistic regression when training data is scarce.

Practical Applications of Naive Bayes: Email Classifier—Spam or Ham?

Let’s see a practical application of naive Bayes for classifying email as spam or ham. We will use sklearn.naive_bayes to train a spam classifier in Python*.

import os
import os
import io
import numpy
from pandas import DataFrame
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB

The following example will be using the MultinomialNB operation.

Creating the readFiles function:

def readFiles(path):
    for root, dirnames, filenames in os.walk(path):
        for filename in filenames:
            path = os.path.join(root, filename)
            inBody = False
            lines = []
            f = io.open(path, 'r', encoding='latin1')
            for line in f:
                if inBody:
                    lines.append(line)
                elif line == '\n':
                    inBody = True
            f.close()
            message = '\n'.join(lines)
            yield path, message

Creating a function to help us create a dataFrame:

def dataFrameFromDirectory(path, classification):
    rows = []
    index = []
    for filename, message in readFiles(path):
        rows.append({'message': message, 'class': classification})
        index.append(filename)
    return DataFrame(rows, index=index)
data = DataFrame({'message': [], 'class': []})
data = data.append(dataFrameFromDirectory('/…/SPAMORHAM /emails/spam/', 'spam'))
data = data.append(dataFrameFromDirectory('/…/SPAMORHAM/emails/ham/', 'ham'))

Let's have a look at that dataFrame:

data.head()

 

      class message

 

      /…/SPAMORHAM/emails/spam/00001.7848dde101aa985090474a91ec93fcf0 spam <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Tr...
      /…/SPAMORHAM/emails/spam/00002.d94f1b97e48ed3b553b3508d116e6a09 spam 1) Fight The Risk of Cancer!\n\nhttp://www.adc...
      /…/SPAMORHAM/emails/spam/00003.2ee33bc6eacdb11f38d052c44819ba6c spam 1) Fight The Risk of Cancer!\n\nhttp://www.adc...
      /…/SPAMORHAM/emails/spam/00004.eac8de8d759b7e74154f142194282724 spam ##############################################...
      /…/SPAMORHAM/emails/spam/00005.57696a39d7d84318ce497886896bf90d spam I thought you might like these:\n\n1) Slim Dow...

Now we will use a CountVectorizer to split up each message into its list of words, and throw that into a MultinomialNB classifier. Call the fit() method:

vectorizer = CountVectorizer()
counts = vectorizer.fit_transform(data['message'].values)
counts

      <3000x62964 sparse matrix of type '<type 'numpy.int64'>'

        with 429785 stored elements in Compressed Sparse Row format>

Now we are using MultinomialNB():

classifierModel = MultinomialNB()

      ## This is the target

      ## Class is the target

targets = data['class'].values

      ## Using counts to fit the model

classifierModel.fit(counts, targets)
MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)

The classifierModel is ready. Now, let’s prepare sample email messages to see how the model works.
Email number 1 is Free Viagra now!!!, Email number 2 is A quick brown fox is not ready, and so on:

examples = ['Free Viagra now!!!',"A quick brown fox is not ready","Could you bring me the black coffee as well?","Hi Bob, how about a game of golf tomorrow, are you FREE?","Dude , what are you saying","I am FREE now, you can come","FREE FREE FREE Sex, I am FREE","CENTRAL BANK OF NIGERIA has 100 Million for you","I am not available today, meet Sunday?"]
example_counts = vectorizer.transform(examples)

Now we are using the classifierModel to predict:

predictions = classifierModel.predict(example_counts)

Let’s check the prediction for each email:

predictions

   array(['spam', 'ham', 'ham', 'ham', 'ham', 'ham', 'spam', 'spam', 'ham'],
      dtype='|S4')

Therefore, the first email is spam, the second is ham, and so on.

End Notes

We hope you have gained a clear understanding of the mathematical concepts and principles of naive Bayes using this guide. It is an extremely simple algorithm, with oversimplified assumptions at times, that might not stand true in many real-world scenarios. In this article we explained why naive Bayes often produces decent results, despite these facts. We feel naive Bayes is a very good algorithm and its performance, despite its simplicity, is astonishing.

Viewing all 3384 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>