Quantcast
Viewing all 672 articles
Browse latest View live

Threading in Intel® IPP

In Intel® IPP 8.2 and later versions, multi-threading (internal threading) libraries are deprecated due to issues with performance and interoperability with other threading models, but made available for legacy applications. Multi-threaded static and dynamic libraries are available as a separate download to support legacy applications. For new applications development, highly recommended to use the single-threaded versions with application-level threading (as  shown in the below picture).

Image may be NSFW.
Clik here to view.

 

Intel® IPP 8.2 and later versions installation will have single threaded libraries in the following directory Structure

<ipp directory>lib/ia32– Single-threaded Static and Dynamic for IA32 architecture

<ipp directory>lib/intel64- Single-threaded Static and Dynamic for Intel 64 architecture

Static linking (Both single threaded and Multi-threaded libraries)      

  • Windows* OS: mt suffix in a library name (ipp<domain>mt.lib)
  • Linux* OS and OS X*: no suffix in a library name (libipp<domain>.a)

Dynamic Linking: Default (no suffix)

  • Windows* OS: ipp<domain>.lib
  • Linux* OS: libipp<domain>.a
  • OS X*: libipp<domain>.dylib

Q: Does Intel® IPP supports external multi-threading? Thread safe?

Ans: Yes, Intel® IPP supports external threading as in the below picture. User has option to use different threading models like Intel TBB, Intel Cilk Plus, Windows * threads, OpenMP or PoSIX. All Intel® Integrated Performance Primitives functions are thread-safe.

Q: How to get Intel® IPP threaded libraries?

Ans: While Installing Intel IPP, choose ‘custom’ installation option.  Then you will get option to select threaded libraries for different architecture.

Image may be NSFW.
Clik here to view.

To select right package of threaded libraries, right click and enable ‘Install’ option.

Image may be NSFW.
Clik here to view.

After selecting threaded libraries, selection option will get highlighted with Image may be NSFW.
Clik here to view.
 mark and memory requirement for threaded libraries will get highlighted.

Image may be NSFW.
Clik here to view.

Threading in Intel® IPP 8.1 and earlier versions

Threading, within the deprecated multi-threaded add-on packages of the Intel® IPP library, is accomplished by use of the Intel® OpenMP* library. Intel® IPP 8.0 continues the process of deprecating threading inside Intel IPP functions that was started in version 7.1. Though not installed by default, the threaded libraries can be installed so code written with these libraries will still work as before. However, moving to external threading is recommended.

Q: How can I determine the number of threads the Intel IPP creates?
Ans: You can use the function ippGetNumThreads to find the number of threads created by the Intel IPP.

Q: How do I control the number of threads the Intel IPP creates?
Ans: Call the function ippSetNumThreads to set the number of threads created.

Q: Is it possible to prevent Intel IPP from creating threads?
Ans: Yes, if you are calling the Intel IPP functions from multiple threads, it is recommended to have Intel IPP threading turned off. There are 3 ways to disable multi-threading:

  • Link to the non-threaded static libraries
  • Build and link to a custom DLL using the non-threaded static libraries
  • Call ippSetNumThread(1)

Q: When my application calls Intel IPP functions from a separate thread, the application hangs; how do I resolve this?

Ans: This issue occurs because the threading technology used in your application and in the Intel IPP (which has OpenMP threading) is incompatible. The ippSetNumThreads function has been developed so that threading can be disabled in the dynamic libraries. Please also check the sections above for other ways to prevent Intel IPP functions from creating threads.

Q: Which Intel IPP functions contain OpenMP* code?

Ans: "ThreadedFunctionsList.txt" file under ‘doc’ folder under product installation directory provide detailed list of threaded functions in Intel IPP Library. The list is updated in each release.

Please let us know if you have any feedback on deprecations via the feedback URL

  • threaded static library
  • IPP threaded function
  • ipp threaded library
  • intel IPP threading
  • threading in IPP
  • threading in intel IPP
  • intel IPP and TBB
  • Desarrolladores
  • Android*
  • Linux*
  • Microsoft Windows* (XP, Vista, 7)
  • Microsoft Windows* 10
  • Microsoft Windows* 8.x
  • Tizen*
  • Yocto Project
  • Android*
  • Code for Good
  • Desarrollo de juegos
  • Internet de las cosas
  • Tizen*
  • Windows*
  • .NET*
  • C#
  • C/C++
  • Intermedio
  • Intel® System Studio
  • Intel® Integrated Performance Primitives
  • Intel® C++ Studio XE
  • Intel® Advanced Vector Extensions
  • Intel® Streaming SIMD Extensions
  • Herramientas de desarrollo
  • Empresa
  • Atención de la salud
  • Procesadores Intel® Atom™
  • Internet de las cosas
  • Procesamiento de medios
  • Optimización
  • Migración
  • Subprocesos
  • Sistemas integrados
  • Portátil
  • Teléfono
  • Equipo Tableta
  • Mejora del rendimiento
  • Bibliotecas
  • Desarrollo de Multi-subprocesos
  • Última actualización: 

    Martes, 7 abril, 2015

    Threading Intel® Integrated Performance Primitives Image Resize with Intel® Threading Building Blocks

    Threading Intel® IPP Image Resize with Intel® TBB.pdf (157.18 KB) :Download Now

     

    Introduction

    The Intel® Integrated Performance Primitives (Intel® IPP) library provides a wide variety of vectorized signal and image processing functions. Intel® Threading Building Blocks (Intel® TBB) adds simple but powerful abstractions for expressing parallelism in C++ programs. This article presents a starting point for using these tools together to combine the benefits of vectorization and threading to resize images.   

    From Intel® IPP 8.2 onwards multi-threading (internal threaded) libraries are deprecated due to issues with performance and interoperability with other threading models, but made available for legacy applications. However, multithreaded programming is now main stream and there is a rich ecosystem of threading tools such as Intel® TBB.  In most cases, handling threading at an application level (that is, external/above the primitives) offers many advantages.  Many applications already have their own threading model, and application level/external threading gives developers the greatest level of flexibility and control.  With a little extra effort to add threading to applications it is possible to meet or exceed internal threading performance, and this opens the door to more advanced optimization techniques such as reusing local cache data for multiple operations.  This is the main reason to start deprecating internal threading in the latest releases.

    Getting started with parallel_for

    Intel® TBB’s parallel_for offers an easy way to get started with parallelism, and it is one of the most commonly used parts of Intel® TBB. Any for() loop in the applications, where  each iteration can be done independently and the order of execution doesn’t matter.  In these scenarios, Intel® TBB parallel_for is useful and takes care of most details, like setting up a thread pool and a scheduler. You supply the partitioning scheme and the code to run on separate threads or cores. More sophisticated approaches are possible. However, the goal of this article and sample code is to provide a simple starting point and not the best possible threading configuration for every situation.

    Intel® TBB’s parallel_for takes 2 or 3 arguments. 

    parallel_for ( range, body, optional partitioner ) 

    The range, for this simplified line-based partitioning, is specified by:

    blocked_range<int>(begin, end, grainsize)

    This provides information to each thread about which lines of the image it is processing. It will automatically partition a range from begin to end in grainsize chunks.  For Intel® TBB the grainsize is automatically adjusted when ranges don't partition evenly, so it is easy to accommodate arbitrary sizes.

    The body is the section of code to be parallelized. This can be implemented separately (including as part of a class); though for simple cases it is often convenient to use a lambda expression. With the lambda approach the entire function body is part of the parallel_for call. Variables to pass to this anonymous function are listed in brackets [alg, pSrc, pDst, stridesrc_8u, …] and range information is passed via blocked_range<int>& range.

    This is a general threading abstraction which can be applied to a wide variety of problems.  There are many examples elsewhere showing parallel_for with simple loops such as array operations.  Tailoring for resize follows the same pattern.

    External Parallelization for Intel® IPP Resize

    A threaded resize can be split into tiles of any shape. However, it is convenient to use groups of rows where the tiles are the width of the image.

    Each thread can query range.begin(), range.size(), etc. to determine offsets into the image buffer. Note: this starting point implementation assumes that the entire image is available within a single buffer in memory. 

    The new image resize functions in Intel® IPP 7.1 and later versions, new approach has many advantages like

    • IppiResizeSpec holds precalculated coefficients based on input/output resolution combination. Multiple resizes which can be completed without recomputing them.
    • Separate functions for each interpolation method.
    • Significantly smaller executable size footprint with static linking.
    • Improved support for threading and tiled image processing.
    • For more information please refer to article : Resize Changes in Intel® IPP 7.1

    Before starting resize, the offsets (number of bytes to add to the source and destination pointers to calculate where each thread’s region starts) must be calculated. Intel® IPP provides a convenient function for this purpose:

    ippiResizeGetSrcOffset

    This function calculates the corresponding offset/location in the source image for a location in the destination image. In this case, the destination offset is the beginning of the thread’s blocked range.

    After this function it is easy to calculate the source and destination addresses for each thread’s current work unit:

    pSrcT=pSrc+(srcOffset.y*stridesrc_8u);
    pDstT=pDst+(dstOffset.y*stridedst_8u);

    These are plugged into the resize function, like this:

    ippiResizeLanczos_8u_C1R(pSrcT, stridesrc_8u, pDstT, stridedst_8u, dstOffset, dstSizeT, ippBorderRepl, 0, pSpec, localBuffer);

    This specifies how each thread works on a subset of lines of the image. Instead of using the beginning of the source and destination buffers, pSrcT and pDstT provide the starting points of the regions each thread is working with. The height of each thread's region is passed to resize via dstSizeT. Of course, in the special case of 1 thread these values are the same as for a nonthreaded implementation.

    Another difference to call out is that since each thread is doing its own resize simultaneously the same working buffer cannot be used for all threads. For simplicity the working buffer is allocated within the lambda function with scalable_aligned_malloc, though further efficiency could be gained by pre-allocating a buffer for each thread.

    The following code snippet demonstrates how to set up resize within a parallel_for lambda function, and how the concepts described above could be implemented together.  

     Click here for full source code.

    By downloading this sample code, you accept the End User License Agreement.

    parallel_for( blocked_range<int>( 0, pnminfo_dst.imgsize.height, grainsize ),
                [pSrc, pDst, stridesrc_8u, stridedst_8u, pnminfo_src,
                pnminfo_dst, bufSize, pSpec]( const blocked_range<int>& range )
            {
                Ipp8u *pSrcT,*pDstT;
                IppiPoint srcOffset = {0, 0};
                IppiPoint dstOffset = {0, 0};
    
                // resized region is the full width of the image,
                // The height is set by TBB via range.size()
                IppiSize  dstSizeT = {pnminfo_dst.imgsize.width,(int)range.size()};
    
                // set up working buffer for this thread's resize
                Ipp32s localBufSize=0;
                ippiResizeGetBufferSize_8u( pSpec, dstSizeT,
                    pnminfo_dst.nChannels, &localBufSize );
    
                Ipp8u *localBuffer =
                    (Ipp8u*)scalable_aligned_malloc( localBufSize*sizeof(Ipp8u), 32);
    
                // given the destination offset, calculate the offset in the source image
                dstOffset.y=range.begin();
                ippiResizeGetSrcOffset_8u(pSpec,dstOffset,&srcOffset);
    
                // pointers to the starting points within the buffers that this thread
                // will read from/write to
                pSrcT=pSrc+(srcOffset.y*stridesrc_8u);
                pDstT=pDst+(dstOffset.y*stridedst_8u);
    
    
                // do the resize for greyscale or color
                switch (pnminfo_dst.nChannels)
                {
                case 1: ippiResizeLanczos_8u_C1R(pSrcT,stridesrc_8u,pDstT,stridedst_8u,
                            dstOffset,dstSizeT,ippBorderRepl, 0, pSpec,localBuffer); break;
                case 3: ippiResizeLanczos_8u_C3R(pSrcT,stridesrc_8u,pDstT,stridedst_8u,
                            dstOffset,dstSizeT,ippBorderRepl, 0, pSpec,localBuffer); break;
                default:break; //only 1 and 3 channel images
                }
    
                scalable_aligned_free((void*) localBuffer);
            });
     

    As you can see, a threaded implementation can be quite similar to single threaded.  The main difference is simply that the image is partitioned by Intel® TBB to work across several threads, and each thread is responsible for groups of image lines. This is a relatively straightforward way to divide the task of resizing an image across multiple cores or threads.

    Conclusion

    Intel® IPP provides a suite of SIMD-optimized functions. Intel® TBB provides a simple but powerful way to handle threading in Intel® IPP applications. Using them together allows access to great vectorized performance on each core as well as efficient partitioning to multiple cores. The deeper level of control available with external threading enables more efficient processing and better performance. 

    Example code: As with other  Intel® IPP sample code, by downloading you accept the End User License Agreement.

  • resize; Intel IPP threading
  • IPP threading
  • TBB threading
  • IPP & TBB
  • Desarrolladores
  • Android*
  • Linux*
  • Microsoft Windows* (XP, Vista, 7)
  • Microsoft Windows* 10
  • Microsoft Windows* 8.x
  • Tizen*
  • Yocto Project
  • Android*
  • Code for Good
  • Internet de las cosas
  • Tizen*
  • Windows*
  • C/C++
  • Avanzado
  • Intermedio
  • Intel® System Studio
  • Intel® Integrated Performance Primitives
  • Módulos Intel® de subprocesamiento
  • Intel® Advanced Vector Extensions
  • Intel® Streaming SIMD Extensions
  • OpenMP*
  • Herramientas de desarrollo
  • Procesadores Intel® Atom™
  • Internet de las cosas
  • Procesamiento de medios
  • Optimización
  • Computación en paralelo
  • Subprocesos
  • Sistemas integrados
  • Portátil
  • Teléfono
  • Equipo Tableta
  • Escritorio
  • Adjuntos protegidos: 

    AdjuntoTamaño
    DescargarImage may be NSFW.
    Clik here to view.
    tbb-resize-simple.cpp
    14.8 KB
  • Dirección URL
  • Ejemplo de código
  • Mejora del rendimiento
  • Bibliotecas
  • Desarrollo de Multi-subprocesos
  • IPP-Learn
  • Última actualización: 

    Martes, 7 abril, 2015

    Edición más reciente por: 

    Naveen Gv (Intel)

    Coautores: 

    Naveen Gv (Intel)

    Intel® IPP - Threading / OpenMP* FAQ

    In Intel® IPP 8.2 and later versions, multi-threading (internal threading) libraries are deprecated due to issues with performance and interoperability with other threading models, but made available for legacy applications. Multi-threaded static and dynamic libraries are available as a separate download to support legacy applications. For new applications development, highly recommended to use the single-threaded versions with application-level threading (as  shown in the below picture).

    Image may be NSFW.
    Clik here to view.

    Intel® IPP 8.2 and later versions installation will have single threaded libraries in the following directory Structure

    <ipp directory>lib/ia32– Single-threaded Static and Dynamic for IA32 architecture

    <ipp directory>lib/intel64 - Single-threaded Static and Dynamic for Intel 64 architecture

    Static linking (Both single threaded and Multi-threaded libraries)             

    • Windows* OS: mt suffix in a library name (ipp<domain>mt.lib)
    • Linux* OS and OS X*: no suffix in a library name (libipp<domain>.a)

    Dynamic Linking: Default (no suffix)

    • Windows* OS: ipp<domain>.lib
    • Linux* OS: libipp<domain>.a
    • OS X*: libipp<domain>.dylib

    Q: Does Intel® IPP supports external multi-threading? Thread safe?

    Answer: Yes, Intel® IPP supports external threading as in the below picture. User has option to use different threading models like Intel TBB, Intel Cilk Plus, Windows * threads, OpenMP or PoSIX. All Intel® Integrated Performance Primitives functions are thread-safe.

    Q: How to get Intel® IPP threaded libraries?

    Answer: While Installing Intel IPP, choose ‘custom’ installation option.  Then you will get option to select threaded libraries for different architecture.

    Image may be NSFW.
    Clik here to view.

    To select right package of threaded libraries, right click and enable ‘Install’ option.

    Image may be NSFW.
    Clik here to view.

    After selecting threaded libraries, selection option will get highlighted with  Image may be NSFW.
    Clik here to view.
    mark and memory requirement for threaded libraries will get highlighted.

    Image may be NSFW.
    Clik here to view.

    Threading in Intel® IPP 8.1 and earlier versions

    Threading, within the deprecated multi-threaded add-on packages of the Intel® IPP library, is accomplished by use of the Intel® OpenMP* library. Intel® IPP 8.0 continues the process of deprecating threading inside Intel IPP functions that was started in version 7.1. Though not installed by default, the threaded libraries can be installed so code written with these libraries will still work as before. However, moving to external threading is recommended.

    Q: How can I determine the number of threads the Intel IPP creates?
    Answer: You can use the function ippGetNumThreads to find the number of threads created by the Intel IPP.

    Q: How do I control the number of threads the Intel IPP creates?
    Ans: Call the function ippSetNumThreads to set the number of threads created.

    Q: Is it possible to prevent Intel IPP from creating threads?
    Ans: Yes, if you are calling the Intel IPP functions from multiple threads, it is recommended to have Intel IPP threading turned off. There are 3 ways to disable multi-threading:

    • Link to the non-threaded static libraries
    • Build and link to a custom DLL using the non-threaded static libraries
    • Call ippSetNumThread(1)

    Q: When my application calls Intel IPP functions from a separate thread, the application hangs; how do I resolve this?

    Ans: This issue occurs because the threading technology used in your application and in the Intel IPP (which has OpenMP threading) is incompatible. The ippSetNumThreads function has been developed so that threading can be disabled in the dynamic libraries. Please also check the sections above for other ways to prevent Intel IPP functions from creating threads.

    Q: Which Intel IPP functions contain OpenMP* code?

    Ans: "ThreadedFunctionsList.txt" file under ‘doc’ folder under product installation directory provide detailed list of threaded functions in Intel IPP Library. The list is updated in each release.

     

    Please let us know if you have any feedback on deprecations via the feedback URL

     

  • libguide
  • libiomp5md.dll
  • libguide40.dll
  • libiomp5.so
  • OMP_NUM_THREADS
  • threaded static library
  • ThreadedFunctionsList
  • ippSetNumThreads()
  • Desarrolladores
  • Android*
  • Apple OS X*
  • Linux*
  • Microsoft Windows* (XP, Vista, 7)
  • Microsoft Windows* 10
  • Microsoft Windows* 8.x
  • Tizen*
  • Yocto Project
  • Android*
  • Internet de las cosas
  • Tizen*
  • .NET*
  • C#
  • C/C++
  • Principiante
  • Intermedio
  • Intel® Composer XE
  • Intel® System Studio
  • Intel® Integrated Performance Primitives
  • Intel® Advanced Vector Extensions
  • Intel® Streaming SIMD Extensions
  • OpenMP*
  • Herramientas de desarrollo
  • Procesadores Intel® Atom™
  • Procesadores Intel® Core™
  • Internet de las cosas
  • Optimización
  • Computación en paralelo
  • Subprocesos
  • Sistemas integrados
  • Portátil
  • Teléfono
  • Servidor
  • Equipo Tableta
  • Escritorio
  • Mejora del rendimiento
  • Bibliotecas
  • Desarrollo de Multi-subprocesos
  • Última actualización: 

    Martes, 7 abril, 2015

    What is "Standard Manageability?"


    If you have an Intel AMT system and cannot figure out why you are getting error messages when trying to make API calls related to certain Intel AMT features, you may have a system that support Intel Standard Manageability.

    You can use WS-Management commands to detect your platform's capabilities. See the Discovery Sample in the Intel AMT SDK located at <SDKRoot>\Windows\Intel_AMT\Samples\Discovery for an example.  Also, messages displayed by these platforms in the MEBx and the WebUI indicate Intel Standard Manageability, instead of Intel AMT.

    So what is Standard Manageability? Standard Manageability systems come with a subset of Intel AMT available features.  Standard Manageability are not branded as Intel vPro. These systems are upgradeable to the full Intel AMT version capabilities.

    The Standard Manageability SKU was introduced with Intel AMT Release 5.0. The following Intel AMT features are NOT included or supported on platforms with this SKU:

    • Remote Access, including Fast Call for Help and Remote Scheduled Maintenance
    • Local user-initiated call for help
    • Microsoft Network Access Protection (NAP)
    • Wireless connections to the Manageability Engine
    • Access Monitor
    • Alarm Clock (out-of-band & in-band from release 9.0)
    • KVM

    Note: From Intel AMT Release 6.0, the Access Monitor and Microsoft Network Access Protection (NAP) are supported in this SKU.

    You can detect the SKU of a platform by looking for the following CIM objects:

    On an Intel AMT SKU, there will be:

    • An instance of CIM_RegisteredProfile with a RegisteredName equal to
      • “Intel(r) AMT” and an InstanceID equal to 
      • “Intel(r) ME:Intel(r) AMT”
    • An instance of CIM_ComputerSystem with an ElementName of 
      • “Intel(r) AMT Subsystem”

    On a Standard Manageability SKU, there will be:

    • An instance of CIM_RegisteredProfile with a RegisteredName equal to 
      • “Intel(r) Std. Mgt.” and an InstanceID equal to 
      • “Intel(r) ME:Intel(r) Std. Mgt.”
    • An instance of CIM_ComputerSystem with an ElementName of 
      • “Intel(r) Std. Mgt. Subsystem”.

    For more information, please see the Support for Other Intel Platforms section of the Intel AMT Implementation and Reference Guide.

  • Standard Manageability
  • Upgradeable
  • Features
  • Intel AMT
  • Imagen del icono: 

    Image may be NSFW.
    Clik here to view.
  • Tecnología Intel® vPro™
  • Empresas pequeñas
  • Tecnología Intel® Active Management
  • C/C++
  • Cliente empresarial
  • Desarrolladores
  • Incluir en RSS: 

    1
  • Intermedio
  • Intel® RealSense™ — образец кода Blockhead

    Download Blockhead Code Sample

    Аннотация

    В этом образце кода демонстрируется использование Intel® RealSense™ SDK для Windows* в классическом приложении на C#/WPF. Образец приложения под названием BlockHeadиспользует три интересных функции Intel RealSense SDK:

    • получает и отображает цветное изображение с камеры RGB;
    • получает оценочные данные о расположении лица и положении головы;
    • получает и анализирует данные о выражении лица.

    (Примечание. Для реализации полной функциональности этого приложения требуется направленная на пользователя трехмерная камера.)

    Посмотрите короткое видео о BlockHeadтут. 

    Введение в приложение Blockhead

    Как показано на рис. 1, приложение отображает поток цветовых данных в элементе управления WPF Image и в реальном времени накладывает мультипликационное изображение на лицо пользователя. 

    Image may be NSFW.
    Clik here to view.
    Superimposed cartoon image

    Рисунок 1.Наложение мультипликационного изображения на лицо пользователя

    Мультипликационное изображение программным образом формируется в реальном времени на основе данных, получаемых от SDK.

    • Изображение масштабируется в соответствии с лицом пользователя (уменьшается, когда пользователь отодвигает голову от камеры, и увеличивается, когда пользователь приближает голову к камере) на основе информации о прямоугольной зоне лица.
    • Изображение наклоняется влево и вправо в зависимости от положения головы пользователя (поворот вокруг продольной оси).
    • Содержимое изображения изменяется на основе получения и анализа данных о выражении лица пользователя (см. рис. 2).

    Image may be NSFW.
    Clik here to view.
    Expressions Detected in Real Time

    Рисунок 2.Распознавание улыбки, высунутого языка, воздушного поцелуя и открытого рта в реальном времени

    Подробные сведения

    Для этого простого демонстрационного приложения графика была создана в графическом редакторе и записана в виде PNG-файлов. Вместо этих изображений можно использовать высококачественные изображения с различными уровнями прозрачности, фотографии друзей, карикатуры и прочее для достижения более интересных визуальных эффектов.

    Различные преобразования (например, ScaleTransform, RotateTransform) применяются к объекту изображения для изменения его положения в соответствии с данными Intel RealSense SDK о положении головы. Эти данные включают расположение лица, расположение головы и данные распознавания выражения лица.

    SDK может фиксировать около 20 различных выражений лица, которые затем можно анализировать в приложении. В этом приложении основное внимание уделяется выражениям лица с различными очертаниями рта: EXPRESSION_KISS, EXPRESSION_MOUTH_OPEN, EXPRESSION_SMILE и EXPRESSION_TONGUE_OUT. При этом можно без труда расширить возможности приложения, чтобы также использовать информацию о положении головы, глаз и бровей для определения выражения лица.

    Ознакомьтесь

    Чтобы узнать больше об этом приложении, просмотреть код и развить его, добавив более интересные возможности, опирающиеся на Intel RealSense SDK, загрузите этот пакет здесь.

    О технологии Intel® RealSense™

    Чтобы приступить к работе и узнать больше о Intel RealSense SDK для Windows, перейдите по адресу https://software.intel.com/ru-ru/realsense/intel-realsense-sdk-for-windows.

    Об авторе

    Брайан Браун — инженер по разработке программных приложений в подразделении Developer Relations корпорации Intel. Его профессиональный опыт охватывает создание программного обеспечения и электроники, а также проектирование систем. Среди интересующих его направлений — применение технологий естественного взаимодействия и интерфейсов между компьютером и мозгом. Он активно участвует в нескольких программах разработки различных передовых технологиях в этих областях.

  • Blockhead
  • face location
  • face tracking
  • Facial analysis
  • Intel® RealSense™ Technology
  • Intel® RealSense™
  • Intel RealSense
  • RealSense SDK
  • Desarrolladores
  • Microsoft Windows* 8.x
  • Tecnología Intel® RealSense™
  • Windows*
  • C#
  • Intermedio
  • SDK de Intel® RealSense™
  • Tecnología Intel® RealSense™
  • Cámara F200 frontal
  • Portátil
  • Equipo Tableta
  • Dirección URL
  • Tecnología Intel® RealSense™
  • Эффективность и Производительность Консольных API на ПК

    Общие сведения о Direct3D* 12
    By: Michael Coppock

    Загрузить PDF

    Аннотация
    Microsoft Direct3D* 12 — важный шаг в развитии технологий игр на ПК. В новой версии разработчики получают более мощные средства контроля над своими играми, могут эффективнее использовать ресурсы ЦП.

     


     

    Содержание

    Введение. 3

    1.0. Хорошо забытое старое. 3

    1.1. Ближе к железу. 4

    2.0. Объект состояния конвейера. 5

    3.0.Привязка ресурсов. 9

    3.1. Опасности, связанные с ресурсами. 10

    3.2. Управление резидентностью ресурсов. 11

    3.3. Зеркальное копирование состояния. 11

    4.0. Кучи и таблицы.. 12

    4.1. Привязка избыточных ресурсов. 12

    4.2. Дескрипторы.. 13

    4.3. Кучи. 13

    4.4. Таблицы.. 14

    4.5. Эффективность и работа без привязки. 15

    4.6. Обзор контекста отрисовки. 15

    5.0. Наборы.. 17

    5.1. Избыточные команды отрисовки. 17

    5.2. Что такое наборы?. 18

    5.3. Эффективность кода. 19

    6.0. Списки команд. 21

    6.1. Параллельное создание команд. 21

    6.2. Списки и очередь. 22

    6.3. Поток очереди команд. 23

    7.0.Динамические кучи. 24

    8.0. Параллельная работа ЦП.. 25

    Ссылки и полезные материалы.. 29

    Уведомления и примечания. 29

     

    Ссылки и полезные материалы

    Уведомления и примечания

    Введение

    На конференции GDC 2014 корпорация Microsoft объявила важную новость для всего рынка игр для ПК в 2015 году — выпуск новой версии Direct3D, а именно версии 12. В D3D 12 создатели вернулись к низкоуровневому программированию: оно дает разработчикам игр более полный контроль и много новых интересных возможностей. Группа разработки D3D 12 старается снизить издержки при задействовании ЦП и повысить масштабиру­е­мость, чтобы полнее нагружать ядра ЦП. Цель состоит в повышении эффективности и  производительности консольных API, чтобы игры могли эффективнее использовать ресурсы ЦП/ГП. В мире игр для ПК большую часть работы, а то и всю работу часто выполняет один-единственный поток ЦП. Другие потоки заняты только операционной системой и другими системными задачами. Существует совсем немного действительно многопоточных игр для ПК. Microsoft стремится изменить эту ситуацию в наборе D3D 12, который является надстройкой над функциональностью рендеринга D3D 11. Это означает, что на всех современных ГП можно запускать D3D 12, поскольку при этом будут эффективнее задействованы современные многоядерные ЦП и ГП. Для использования всех преимуществ D3D 12 не нужно покупать новый графический процессор. Действительно, у игр на ПК с процессором Intel® очень яркое будущее.

    1.0 Хорошо забытое старое

    Низкоуровневое программирование широко применяется в отрасли консолей, поскольку характеристики и устройство каждой модели консолей неизменны. Разработчики игр могут подолгу отлаживать свои игры, чтобы выжать всю возможную производительность из Xbox One* или PlayStation* 4. С другой стороны, ПК по своей природе — это гибкая платформа с бесчисленным множеством разновидностей и вариаций. При планировании разработки новой игры для ПК требуется учитывать очень много факторов. Высокоуровневые API, такие как OpenGL* и Direct3D*, помогают упростить разработку. Эти API выполняют всю «черную работу», поэтому разработчики могут сосредоточиться собственно на играх. Проблема же заключается в том, что и API, и (в несколько меньшей степени) драйверы достигли уже такого уровня сложности, что они могут увеличить объем потребляемых ресурсов при рендеринге кадров, что приводит к снижению произво­дительности. Именно здесь на сцену выходит низкоуровневое программирование.

    Первая эпоха низкоуровневого программирования на ПК окончилась вместе с прекращением использования MS-DOS*. На смену пришли API разных поставщиков. После 3Dglide* компании 3DFX* появились такие API, как Direct3D. ПК проиграли в производительности, получив взамен столь необходимую гибкость и удобство. Рынок оборудования стал крайне сложным, с огромным множеством доступных аппаратных решений. Время разработки увеличилось, поскольку разработчики, естественно, стремились к тому, чтобы в их игры могли бы играть все пользователи. При этом перемены произошли не только на стороне программ, но и в оборудовании: эффективность ЦП с точки зрения потребления электроэнергии стала важнее, чем их производительность. Теперь вместо того, чтобы гнаться за увеличением тактовой частоты, больше внимания уделяется использованию нескольких ядер и потоков ЦП, параллельному рендерингу на современных ГП. Настала пора применить в области игр для ПК некоторые методики, используемые в консольных играх. Пора эффективнее, полнее использовать все доступные ядра и потоки. Словом, пора перейти в XXI век в мире игр для ПК.

    1.1 Ближе к железу

    Чтобы приблизить игры к «железу», нужно снизить сложность и размер API и драйвера. Между оборудованием и самой игрой должно быть меньше промежуточных уровней. Сейчас API и драйвер тратят слишком много времени на преобразование команд и вызовов. Некоторые или даже многие эти процедуры будут снова отданы разработчикам игр. За счет снижения издержек в D3D 12 повысится производительность, а за счет уменьшения количества промежуточных уровней обработки между игрой и оборудованием ГП игры будут быстрее работать и лучше выглядеть. Разумеется, у медали есть и обратная сторона: некоторые разработчики могут не желать заниматься областями, которые ранее были под контролем API, например программировать управление памятью ГП. Пожалуй, в этой области слово за разработчиками игровых движков, но, впрочем, только время расставит все на свои места. Поскольку выпуск D3D 12 состоится еще не скоро, имеется предостаточно времени для размышлений на эту тему. Итак, как же будут выполнены все эти заманчивые обещания? Главным образом с помощью новых возможностей. Это объекты состояния конвейера, списки команд, наборы и кучи.

    2.0 Объект состояния конвейера

    Прежде чем рассказывать об объекте состояния конвейера (PSO), сначала рассмотрим контекст рендеринга D3D 11, а потом перейдем к изменениям в D3D 12. На рис. 1 показан контекст рендеринга D3D 11 в том виде, в котором его представил Макс Мак-Маллен (Max McMullen), руководитель по разработке D3D, на конференции BUILD 2014 в апреле 2014 года.

    Контекст отрисовки: Direct3D 11

    Image may be NSFW.
    Clik here to view.

    Рисунок 1. Контекст отрисовки D3D 11 [Воспроизводится с разрешения корпорации Майкрософт.]

    Крупные толстые стрелки указывают отдельные состояния конвейера. В соответствии с потребностями игры каждое такое состояние можно получить или задать. Прочие состояния в нижней части - фиксированные состояния функций, такие как поле зрения или прямоугольник обрезки. Другие важные компоненты этой схемы будут пояснены в дальнейших разделах данной статьи. При обсуждении PSO нас интересует только левая часть схемы. В D3D 11 удалось снизить издержки ЦП по сравнению с D3D 9 благодаря малым объектам состояния, но по-прежнему требовалась дополнительная работа драйвера, который должен был брать эти малые объекты состояния и сочетать их с кодом ГП во время рендеринга. Назовем эту проблему издержками аппаратного несоответствия. Теперь посмотрим еще на одну схему с конференции BUILD 2014, показанную на рис. 2.

    Direct3D 11 — издержки состояния конвейера

    Малые объекты состояния à издержки аппаратного несоответствия

    Image may be NSFW.
    Clik here to view.

    Рисунок 2. В конвейере D3D 11 с малыми объектами состояния часто возникают издержки аппаратного несоответствия

    На левой стороне показан конвейер в стиле D3D 9: здесь показано, что использует приложение для выполнения своей работы. Оборудование, показанное на правой стороне схемы на рис. 2, необходимо программировать. Состояние 1 представляет код шейдера. Состояние 2 — это сочетание растеризатора и потока управления, связывающего растеризатор с шейдерами. Состояние 3 — связь между смешением и пиксельным шейдером. Шейдер вертексов D3D влияет на аппаратные состояния 1 и 2, растеризатор — на состояние 2, пиксельный шейдер — на состояния с 1 по 3 и так далее. Драйверы в большинстве случаев не отправляют вызовы одновременно с приложением. Они предпочитают записывать вызовы и дожидаться выполнения работы, чтобы можно было определить, что на самом деле нужно приложению. Это означает дополнительные издержки для ЦП, поскольку старые и устаревшие данные помечаются как «непригодные». Поток управления драйвера проверяет состояние каждого объекта во время рендеринга и программирует оборудование так, чтобы соответствовать заданному игрой состоянию. При этой дополнительной работе возможно исчерпание ресурсов и возникновение затруднений. В идеале, как только игра задает состояние конвейера, драйвер тут же «знает», что нужно игре, и сразу программирует оборудование. На рис. 3 показан конвейер D3D 12, который делает именно это с помощью так называемого объекта состояния конвейера (PSO).

    Direct3D 12 — оптимизациясостояния конвейера

    Группировка конвейера в один объект

    Копирование из PSO в аппаратное состояние

    Image may be NSFW.
    Clik here to view.

    Рисунок 3. Оптимизация состояния конвейера в D3D 12 упорядочивает процесс.

    На рис. 3 показан упорядоченный процесс с уменьшенными издержками. Один PSO с информа­цией о состоянии для каждого шейдера может за одну копию задать все аппаратные состояния. Вспомните, что некоторые состояния были помечены как «прочие» в контексте рендеринга D3D 11. Разработчики D3D 12 осознали важность уменьшения размера PSO и предоставления игре возможности смены цели рендеринга, не затрагивая скомпилированный PSO. Такие вещи, как поле зрения и прямоугольник обрезки, остались отдельными, они программируются вне остального конвейера (рис. 4).

    Контекст рендеринга:
    объект состояния конвейера (PSO)

    Image may be NSFW.
    Clik here to view.

    Рисунок 4. Слева показан новый PSO D3D 12 с увеличенным состоянием для повышения эффективности

    Вместо того чтобы задавать и прочитывать каждое состояние по отдельности, мы получили единую точку, тем самым полностью избавившись от издержек аппаратного несоответствия. Приложение задает PSO нужным образом, а драйвер получает команды API и преобразует их в код ГП без дополнительных издержек, связанных с управлением потоком. Такой подход (более близкий к «железу») означает, что для обработки команд рендеринга требуется меньше циклов, производительность возрастает.

    3.0 Привязка ресурсов

    Перед рассмотрением изменений в привязке ресурсов вспомним, какая модель привязки ресурсов использовалась в D3D 11. На рис. 5 снова показана схема контекста рендеринга: слева — объект состояния конвейера D3D 12, а справа — модель привязки ресурсов D3D 11.

    Контекст отрисовки:
    объект состояния конвейера (PSO)

    Image may be NSFW.
    Clik here to view.

    Рисунок 5. Слева — объект состояния конвейера D3D 12, справа — модель привязки ресурсов D3D 11.

    На рис. 5 принудительные точки привязки находятся справа от каждого шейдера. Принудительная модель привязки означает, что у каждого этапа в конвейере есть определенные ресурсы, на которые можно сослаться. Эти точки привязки ссылаются на ресурсы в памяти ГП. Это могут быть текстуры, цели рендеринга, неупорядоченные представления доступа (UAV) и так далее. Привязки ресурсов используются уже давно, они появились даже раньше, чем D3D. Цель в том, чтобы «за кадром» обработать множество свойств и помочь игре в эффективной отправке команд рендеринга. При этом системе необходимо выполнить анализ множества привязок в трех основных областях. В следующем разделе рассматриваются эти области и их оптимизация в D3D 12.

    3.1 Опасности, связанные с ресурсами

    Опасности обычно связаны с переходами, например с перемещением от цели рендеринга к текстуре. Игра может отрисовать кадр, который должен стать картой среды для сцены. Игра завершает рендеринг карты среды и теперь хочет использовать ее в качестве текстуры. В ходе этого процесса и среда выполнения, и драйвер отслеживают все ресурсы, привязанные как цели рендеринга или как текстуры. Если среда выполнения или драйвер видят какой-либо ресурс, привязанный одновременно и как цель рендеринга, и как текстура, они отменяют более старую по времени привязку и сохраняют более новую. За счет этого игра может переключаться нужным образом, а набор программного обеспечения управляет этим переключением «за кадром». Драйвер также должен очистить конвейер ГП, чтобы можно было использовать цель рендеринга в качестве текстуры. В противном случае пиксели будут прочитаны до того, как они будут удалены из ЦП, и полученный результат будет несогласованным. Собственно говоря, опасность — это все, для чего требуется дополнительная работа ГП с целью получения согласованных данных.

    Как и в других усовершенствованиях в D3D 12, решение здесь состоит в том, чтобы предоставить игре больше возможностей управления. Почему API и драйвер должны выполнять всю работу и отслеживание, когда это всего лишь один момент в обработке кадра? Для переключения от одного ресурса к другому требуется около 1/60 секунды. Можно снизить издержки, передав управление игре, тогда дополнительное время будет израсходовано только один раз, когда игра осуществляет переключение ресурсов (рис. 6).

    D3D12_RESOURCE_BARRIER_DESC Desc;
    Desc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
    Desc.Transition.pResource   = pRTTexture;
    Desc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
    Desc.Transition.StateBefore = D3D12_RESOURCE_USAGE_RENDER_TARGET;
    Desc.Transition.StateAfter  = D3D12_RESOURCE_USAGE_PIXEL_SHADER_RESOURCE;
    pContext->ResourceBarrier( 1, &Desc );
    Рисунок 6. API ограничителя ресурсов, добавленный в D3D 12

    API ограничителя ресурсов, показанный на рис. 6, объявляет ресурс, его начальное использование и целевое использование, после чего следует вызов, чтобы сообщить выполняемой среде и драйверу о переключении. Переключение становится явным вместо отслеживаемого в рендеринге кадра со множеством условной логики, оно осуществляется один раз за кадр или с такой частотой, с которой оно требуется в игре.

    3.2 Управление резидентностью ресурсов

    D3D 11 (и более старые версии) работают так, как если бы все вызовы были в очереди. Игра считает, что API немедленно выполняет вызов. Но на самом деле это не так. ГП поддерживает очередь команд, в которой все команды откладываются и выполняются позднее. При этом обеспечивается распараллеливание вычислений и более эффективное задействование ГП и ЦП, но требуется отслеживание ссылок и их учет. На учет и отслеживание расходуется достаточно много ресурсов ЦП.

    Чтобы решить эту проблему, игра получает явное управление жизненным циклом ресурсов. В D3D 12 больше не скрывается очередь ГП. Для отслеживания выполнения на ГП добавлен API Fence. Игра может в заданный момент (например, один раз за кадр) проверить, какие ресурсы больше не нужны, и затем высвободить занимаемую ими память. Больше не требуется отслеживать ресурсы в течение всего рендеринга кадра с помощью дополнительной логики, чтобы высвобождать ресурсы и память.

    3.3 Зеркальное копирование состояния

    После оптимизации трех описанных выше областей был обнаружен дополнительный элемент, способный обеспечить прирост производительности, хотя и не столь заметный. Когда задана точка привязки, среда выполнения отслеживает эту точку, чтобы игра могла позднее вызвать Getи узнать, что привязано к конвейеру. Создается зеркальная копия точки привязки. Эта функция выполняет промежуточную работу, чтобы разделенное на компоненты программное обеспечение могло определить текущее состояние контекста рендеринга. После оптимизации привязки ресурсов зеркальные копии состояний больше не нужны. Помимо упразднения управления потоком из трех описанных выше областей также удалены операции Get для зеркальных копий.

    4.0 Кучи и таблицы

    Осталось рассмотреть еще одно важное изменение привязки ресурсов. В конце раздела 4 будет показан весь контекст рендеринга D3D 12. Новый контекст рендеринга D3D 12 — первый шаг на пути к повышению эффективности использования ЦП в API.

    4.1 Привязка избыточных ресурсов

    Проведя анализ нескольких игр, разработчики D3D заметили, что обычно в играх в множестве кадров используется одна и та же последовательность команд. Не только команды, но и привязки остаются точно такими же из кадра в кадр. ЦП создает последовательность привязок (скажем, 12) для рисования объекта в кадре. Зачастую ЦП приходится создавать эти же 12 привязок еще раз для следующего кадра. Почему же не поместить эти привязки в кэш? Разработчикам игр можно предоставить команду, указывающую на кэш, чтобы можно было многократно использовать одинаковые привязки.

    Вразделе 3 мы обсудили очереди. Когда осуществляется вызов, игра исходит из того, что API немедленно выполняет этот вызов. Но на самом деле это не так. Команды помещаются в очередь, все содержимое которой откладывается и выполняется позднее в ГП. Поэтому если изменить одну из этих 12 привязок, о которых мы говорили ранее, то драйвер скопирует все 12 привязок в новое место, изменит копию, затем даст графическому процессору команду начать использовать скопированные привязки. Обычно у большинства из этих 12 привязок значения бывают статическими, а обновление требуется лишь для нескольких динамических значений. Когда игре нужно внести частичные изменения в эти привязки, она копирует все 12 штук, из-за чего наблюдается чрезмерный расход ресурсов ЦП при незначительных изменениях.

    4.2 Дескрипторы

    Что такое дескриптор? Коротко говоря, это фрагмент данных, определяющий параметры ресурсов. По сути, это то, из чего состоит объект представления D3D 11. Управление жизненным циклом на уровне операционной системы отсутствует. Это просто данные в памяти ГП. Здесь содержится информация о типе и формате, счетчик MIP для текстур и указатель на пиксельные данные. Дескрипторы находятся в центре новой модели привязки ресурсов.

    Дескриптор

    Image may be NSFW.
    Clik here to view.

    Рисунок 7. Дескриптор D3D 12 — небольшой фрагмент данных, определяющий параметр ресурса

    4.3 Кучи

    Когда представление задано в D3D 11, оно копирует дескриптор в текущее расположение в памяти ГП, откуда прочитываются дескрипторы. Если задать новое представление в этом же расположении, в D3D 11 дескрипторы будут скопированы в новое расположение в памяти, а ГП в следующем вызове команды рендеринга получит указание читать дескрипторы из этого нового расположения. В D3D 12 игра или приложение получают явное управление созданием дескрипторов, их копированием и пр.

    Кучи дескрипторов

    Image may be NSFW.
    Clik here to view.

    Рисунок 8. Куча дескрипторов является массивом дескрипторов

    Кучи (рис. 8) являются просто очень большим массивом дескрипторов. Можно повторно использовать дескрипторы из предыдущих вызовов рендеринга и кадров. Можно создавать новые при необходимости. Вся разметка находится под управлением игры, поэтому при управлении кучей почти не возникают издержки. Размер кучи зависит от архитектуры ГП. В устаревших маломощных ГП размер может быть ограничен 65 тысячами, а в более мощных ГП ограничение будет определяться объемом памяти. В менее мощных ГП возможно превышение размера кучи. В D3D 12 поддерживается несколько куч и переключение от одной кучи дескрипторов к другой. Тем не менее при переключении между кучами в некоторых ГП происходит сброс данных, поэтому использованием этой функции лучше не злоупотреблять.

    Итак, как сопоставить код шейдеров с определенными дескрипторами или наборами дескрипторов? Ответ – с помощью таблиц.

    4.4 Таблицы

    Таблицы содержат индекс начала и размер в куче. Они являются точками контекста, но не объектами API. При необходимости у каждого этапа шейдера может быть одна или несколько таблиц. Например, шейдер вертекса для вызова рендеринга может содержать таблицу, указывающую на дескрипторы со смещением с 20 по 32 в куче. Когда начнется работа над следующим вызовом рендеринга, смещение может измениться на 32—40.

    Таблицы дескрипторов

    Image may be NSFW.
    Clik here to view.

    Рисунок 9. Таблицы дескрипторов содержат индекс начала и размер в куче дескрипторов

    Используя существующее оборудование, D3D 12 может обрабатывать несколько таблиц на каждое состояние шейдера в PSO. Можно поддерживать одну таблицу лишь с теми данными, которые часто изменяются между вызовами, а вторую таблицу — со статическими данными, неизменными для нескольких вызовов и для нескольких кадров. Это позволит избежать копирования дескрипторов из одного вызова в следующий. Тем не менее у старых ГП действует ограничение в одну таблицу на каждый этап шейдера. Поддержка нескольких таблиц возможна в современном и в перспективном оборудовании.

    4.5 Эффективность и работа без привязки

    Кучи дескрипторов и таблицы применяются в D3D для рендеринга без привязки, причем с возможностью задействования всех аппаратных ресурсов ПК. В D3D 12 поддерживаются любые устройства — от маломощных «систем на кристалле» до высокопроизводительных дискретных графических адаптеров. Благодаря такому универсальному подходу разработчики игр получают разнообразные возможности управления привязками. Кроме того, новая модель включает множественные обновления частоты. Поддерживаются кэшированные таблицы статических привязок с возможностью многократного использования и динамические таблицы для данных, изменяющихся в каждом вызове рендеринга. Таким образом, необходимость копировать все привязки для каждого нового вызова рендерингаотпадает.

    4.6 Обзор контекста отрисовки

    На рис. 10 показан контекст рендеринга с изменениями D3D 12, которые мы уже успели обсудить. Также показан новый объект состояния конвейера и упразднение вызовов Get, но сохранились явные точки привязки D3D 11.

    Контекст отрисовки

    Image may be NSFW.
    Clik here to view.

    Рисунок 10. Контекст отрисовки D3D 12 с изменениями, о которых мы уже успели поговорить.

    Давайте удалим последние остатки контекста рендеринга D3D 11 и добавим таблицы дескрипторов и кучи. Теперь у нас появились таблицы для каждого этапа шейдера (или несколько таблиц, как показано для пиксельного шейдера).

    Контекст отрисовки: Direct3D 12

    Image may be NSFW.
    Clik here to view.

    Рисунок 11. Полный контекст рендеринга D3D 12

    Тонко настраиваемые объекты состояния упразднены, их заменил объект состояния конвейера. Удалено отслеживание опасностей и зеркальное копирование состояния. Принудительные точки привязки заменены на управляемые приложением или игрой объекты памяти. ЦП используется более эффективно, издержки снижены, упразднены поток управления и логика и в API, и в драйвере.

    5.0 Наборы

    Мы завершили рассмотрение нового контекста рендеринга в D3D 12 и увидели, каким образом D3D 12 передает управление игре, приближая ее к «железу». Но этим возможности D3D 12 по повышению эффективности API не ограничиваются. В API по-прежнему существуют издержки, влияющие на производительность, и существуют дополнительные способы повысить эффективность использования ЦП. Как насчет последовательностей команд? Сколько существует повторяющихся последовательностей и как сделать их более эффективными?

    5.1 Избыточные команды рендеринга

    При изучении команд рендеринга в каждом кадре разработчики D3D в Microsoft обнаружили, что при переходе от одного кадра к другому происходит добавление или удаление только 5—10 % последовательностей команд. Остальные последовательности команд используются во множестве кадров. Итак, ЦП в течение 90—95 % времени своей работы повторяет одни и те же последовательности команд!

    Как здесь повысить эффективность? И почему в D3D это не было сделано до сих пор? На конференции BUILD 2014 Макс Мак-Маллен сказал: «Очень сложно создать универсальный и надежный способ записывать команды. Такой способ, чтобы он работал всегда одинаково для разных ГП, с разными драйверами и при этом работал бы быстро». Игре требуется, чтобы все записанные последовательности команд выполнялись так же быстро, как отдельные команды. Что изменилось? D3D. Благодаря новым объектам состояния конвейера, кучам дескрипторов и таблицам состояние, необходимое для записи и воспроизведения команд, значительно упростилось.

    5.2 Что такое наборы?

    Наборы — это небольшие списки команд, которые один раз записываются, после чего их можно многократно использовать без каких-либо ограничений в одном кадре или в нескольких кадрах. Наборы можно создавать в любом потоке и использовать сколько угодно раз. Наборы не привязываются к состоянию объектов PSO. Это означает, объекты PSO могут обновлять таблицу дескрипторов, а при запуске набора для разных привязок игра будет получать разные результаты. Как и в случае с формулами в электронных таблицах Excel*, математика всегда одинаковая, а результат зависит от исходных данных. Существуют определенные ограничения, чтобы гарантировать эффективную реализацию наборов драйвером. Одно из таких ограничений состоит в том, что никакая команда не может сменить цель рендеринга. Но остается еще множество команд, которые можно записать и воспроизводить.

    Наборы

    Image may be NSFW.
    Clik here to view.

    Рисунок 12. Наборы — это часто повторяемые команды, записанные и воспроизводящиеся по мере необходимости

    Слева на рис. 12 — пример контекста рендеринга, последовательность команд, созданных в ЦП и переданных на ГП для выполнения. Справа — два пакета, содержащих записанную последовательность команд для многократного использования в разных потоках. По мере выполнения команд ГП достигает команды на выполнение набора. После этого воспроизводится записанный набор. По завершении ГП возвращается к последовательности команд, продолжает и находит следующую команду выполнения набора. После этого прочитывается и воспроизводится второй набор, после чего выполнение продолжается.

    5.3 Эффективность кода

    Мы рассмотрели управление потоком в ГП. Теперь посмотрим, каким образом наборы упрощают код.

    Пример кода без наборов

    Перед нами страница настройки, задающая состояние конвейера и таблицы дескрипторов. Затем идут два вызова рендеринга объектов. В обоих случаях используется одинаковая последова­тельность команд, различаются только константы. Это типичный код D3D 11.

    // Настройка
    pContext->SetPipelineState(pPSO);
    pContext->SetRenderTargetViewTable(0, 1, FALSE, 0);
    pContext->SetVertexBufferTable(0, 1);
    pContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    Рисунок 14. Настройка этапа в типичном коде D3D 11

     

    // Рисунок 1
    pContext->SetConstantBufferViewTable(D3D12_SHADER_STAGE_PIXEL, 0, 1);
    pContext->SetShaderResourceViewTable(D3D12_SHADER_STAGE_PIXEL, 0, 1);
    pContext->DrawInstanced(6, 1, 0, 0);
    pContext->SetShaderResourceViewTable(D3D12_SHADER_STAGE_PIXEL, 1, 1);
    pContext->DrawInstanced(6, 1, 6, 0);
    Рисунок 15. Рендеринг в типичном коде D3D 11

     

    // Рисунок 2
    pContext->SetConstantBufferViewTable(D3D12_SHADER_STAGE_PIXEL, 1, 1);
    pContext->SetShaderResourceViewTable(D3D12_SHADER_STAGE_PIXEL, 0, 1);
    pContext->DrawInstanced(6, 1, 0, 0);
    pContext->SetShaderResourceViewTable(D3D12_SHADER_STAGE_PIXEL, 1, 1);
    pContext->DrawInstanced(6, 1, 6, 0);
    Рисунок 16. Рендеринг в типичном коде D3D 11

     

    Пример кода с наборами

    Теперь рассмотрим эту же последовательность команд с пакетами в D3D 12. Первый вызов, показанный ниже, создает набор. Это может быть сделано в любом потоке. На следующем этапе создается последовательность команд. Это такие же команды, как и в предыдущем примере

    // Создание набора
    pDevice->CreateCommandList(D3D12_COMMAND_LIST_TYPE_BUNDLE, pBundleAllocator, pPSO, pDescriptorHeap, &pBundle);
    Рисунок 17. Образец кода с созданием набора

     

    // Запись команд
    pBundle->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    pBundle->SetShaderResourceViewTable(D3D12_SHADER_STAGE_PIXEL, 0, 1);
    pBundle->DrawInstanced(6, 1, 0, 0);
    pBundle->SetShaderResourceViewTable(D3D12_SHADER_STAGE_PIXEL, 1, 1);
    pBundle->DrawInstanced(6, 1, 6, 0);
    pBundle->Close();
    Рисунок 18. Образец кода с записью набора

     

    В примерах кода на рис. 17 и 18 достигается такой же результат, как в коде без наборов на рис. 14—16. Хорошо видно, что наборы позволяют существенно сократить количество вызовов, необходимое для выполнения одной и той же задачи. ГП при этом выполняет точно такие же команды и получает такой же результат, но гораздо эффективнее.

    6.0 Списки команд

    Вы уже знаете, каким образом в D3D 12 повышается эффективность использования ЦП и предоставляются более широкие возможности разработчикам с помощью наборов, объектов состояния конвейера, куч дескрипторов и таблиц. Модель объектов состояния конвейера и дескрипторов поддерживает наборы, которые, в свою очередь, используются для широко распространенных и часто повторяющихся команд. Такой упрощенный и «приближенный к железу» подход снижает издержки и позволяет эффективнее использовать ЦП. Ранее мы упомянули, что в играх для ПК большую часть работы, а то и всю работу выполняет только один поток, а остальные потоки занимаются другими системными задачами и процессами ОС. Добиться эффективного использования нескольких ядер или потоков игрой для ПК не так просто. Зачастую для реализации многопоточности в игре требуются существенные затраты ресурсов и труда. Разработчики D3D собираются изменить это положение дел в D3D 12.

    6.1 Параллельное создание команд

    Как уже неоднократно упоминалось выше, отложенное выполнение команд — это модель, при которой создается ощущение, что каждая команда выполняется немедленно, но на самом деле команды помещаются в очередь и выполняются позднее. Эта функция сохраняется в D3D 12, но теперь она является прозрачной для игры. Не существует немедленного контекста, поскольку все откладывается. Потоки могут создавать команды параллельно для формирования списков команд, которые подаются в объект API, который называется очередью команд. ГП не будет выполнять команды, пока они не будут отправлены с помощью очереди команд. Очередь — это порядок следования команд, которые указываются в списке. Чем отличаются списки команд от наборов? Списки команд создаются и оптимизируются, поэтому несколько потоков могут одновременно создавать команды. Списки команд используются однократно, а затем удаляются из памяти; на месте удаленного списка команд записывается новый список. Наборы предназначены для многократного выполнения часто используемых команд рендеринга в одном или в нескольких кадрах.

    В D3D 11 была сделала попытка распараллелить обработку команд; эта функция называлась отложенным контекстом. Но из-за издержек цели по повышению производительности тогда не были достигнуты. Подробный анализ показал множество мест с избыточной последовательной обработкой, что привело к неэффективному распределению нагрузки по ядрам ЦП. Часть издержек с последовательной обработкой была устранена в D3D 12 с помощью средств повышения эффективности использования ЦП, описанных в разделах 2—5.

    6.2 Списки и очередь

    Представьте, что два потока создают список команд рендеринга. Одна последовательность должна быть выполнена перед другой. При наличии опасностей один поток использует ресурс в качестве текстуры, а другой поток использует этот же ресурс в качестве цели рендеринга. Драйвер должен проанализировать использование ресурсов во время рендеринга и устранить опасности, обеспечив согласованность данных. Отслеживание опасностей — одна из областей с последовательными издержками в D3D 11. В D3D 12 за отслеживание опасностей отвечает игра, а не драйвер.

    D3D 11 поддерживается несколько отложенных контекстов, но при их использовании возникает сопутствующая нагрузка. Драйвер отслеживает состояние для каждого ресурса. Поэтому, как только начата запись команд для отложенного контекста, драйвер должен выделять память для отслеживания состояния каждогоиспользуемого ресурса. Память занята, пока идет создание отложенного контекста. По завершении драйвер должен удалить из памяти все объекты отслеживания. Из-за этого возникают ненужные издержки. Игра объявляет максимальное количество списков команд, которые можно создать параллельно на уровне API. После этого драйвер упорядочивает и заранее выделяет все объекты отслеживания в одном согласованном объекте памяти.

    В D3D 11 распространены динамические буферы (буфер контекста, вертексов и т. д.), но «за кадром» остается множество экземпляров удаленных буферов отслеживания памяти. Например, параллельно могут быть созданы два списка команд, и вызвана функция MapDiscard. После отправки списка драйвер должен вмешаться во второй список команд, чтобы исправить информацию об удаленном буфере. Как и в приведенном выше примере с отслеживанием опасностей, здесь возникают значительные издержки. В D3D 12 управление переименованием передано игре, динамического буфера больше нет. Игра получила полное управление. Она создает собственные распределители и может делить буфер на части по мере необходимости. Поэтому команды могут указывать на явным образом заданные точки в памяти.

    Как мы говорили вразделе 3.1,среда выполнения и драйвер отслеживают жизненный цикл ресурсов в D3D 11. Для этого требуется подсчет и отслеживание ресурсов, все операции должны быть сделаны во время отправки. В D3D 12 игра управляет жизненным циклом ресурсов и обработкой опасностей, благодаря чему устраняются издержки последовательной обработки и повышается эффективность использования ЦП. Параллельное создание команд работает эффективнее в D3D 12 с учетом оптимизации в четырех описанных областях, что расширяет возможности распараллеливания нагрузки на ЦП. Кроме того, разработчики D3D создают новую модель драйверов WDDM 2.0 и планируют реализовать дополнительные меры по оптимизации, чтобы снизить нагрузку при отправке списков команд.

    6.3 Поток очереди команд

    Очередь команд

    Image may be NSFW.
    Clik here to view.

    Рисунок 19. Очередь команд с двумя параллельно создаваемыми списками команд и двумя наборами повторяющихся команд

    На рис. 19 показана схема набора израздела 5.2,но с многопоточностью. Очередь команд, показанная слева, представляет собой последовательность событий, отправленных на ГП. Списки команд находятся посередине, а справа — два набора, записанные перед началом сценария. Начиная со списков команд, создаваемых параллельно для разных фрагментов сцены, завершается запись списка команд 1, этот список отправляется в очередь команд, и ГП начинает его выполнять. Параллельно запускается процедура управления потоком очереди команд, а список команд 2 записывается в потоке 2. Пока ГП выполняет список команд 1, поток 2 завершает создание списка команд 2 и отправляет его в очередь команд. Когда очередь команд завершает выполнение списка команд 1, она последовательно переходит к списку команд 2. Очередь команд — это последовательность, в которой ГП должен выполнять команды. Хотя список команд 2 был создан и отправлен в ГП до того, как ГП завершил выполнение списка команд 1, список команд 2 будет выполнен только после завершения выполнения списка команд 1. В D3D 12 поддерживается более эффективное распараллеливание для всего процесса.

    7.0 Динамические кучи

    Как мы уже говорили выше, игра управляет переименованием ресурсов для распараллеливания создания команд. Кроме того, в D3D 12 упрощено переименование ресурсов. В D3D 11 буферы были разделены по типам: были буферы вертексов, констант и индексов. Разработчики игр запросили возможность использовать зарезервированную память так, как им заблагорассудится. И команда D3D выполнила эту просьбу. В D3D 12 разделение буферов по типам отсутствует. Буфер — это просто объем памяти, выделяемый игрой по мере необходимости в размере, необходимом для кадра (или нескольких кадров). Можно даже использовать распределитель кучи с делением по мере необходимости, что повышает эффективность процессов. В D3D 12 также применяется стандартное выравнивание. ГП сможет прочесть данные, если в игре используется стандартное выравнивание. Чем выше уровень стандартизации, тем проще создавать содержимое, работающее с разными моделями ЦП, ГП и другого оборудования. Распределение памяти также является постоянным, поэтому ЦП всегда знает нужный адрес. При этом также повышается эффективность параллельного использования ЦП: поток может направить ЦП на нужный адрес в памяти, после чего ЦП определяет, какие данные нужны для кадра.

    Распределение и перераспределение

    Image may be NSFW.
    Clik here to view.

    Рисунок 20. Распределение и перераспределение буферов

    В верхней части рис. 20 показана модель D3D 11 с типизацией буферов. В нижней части показана новая модель D3D 12, где игра управляет кучей. Вместо выделения отдельной части памяти для буфера каждого типа используется единый постоянный фрагмент памяти. Размер буфера также настраивается игрой на основе потребностей рендеринга текущего кадра или даже нескольких последующих кадров.

    8.0 Параллельная работа ЦП

    Пора собрать все воедино и продемонстрировать, каким образом новые возможности D3D 12 позволяют создать действительно многопоточную игру для ПК. В D3D 12 поддерживается параллельное выполнение нескольких задач. Списки команд и наборы предоставляют возможность параллельного создания и выполнения команд. Наборы позволяют записывать команды и многократно запускать их в одном или в нескольких кадрах. Списки команд могут быть созданы в нескольких потоках и переданы в очередь команд для выполнения графическим процессором. И наконец, буферы с постоянным распределением параллельно создают динамические данные. Параллельная работа поддерживается и в D3D 12, и в WDDM 2.0. В D3D 12 устранены ограничения прежних версий D3D, разработчики могут распараллеливать свои игры или движки любым целесообразным способом.

    Профилирование в D3D11

    Image may be NSFW.
    Clik here to view.

    Рисунок 21. Типичная параллельная обработка в D3D 11. Поток 0 выполняет почти всю работу, остальные потоки используются незначительно

    На схеме на рис. 21 показана типичная игровая нагрузка в D3D 11. Логика приложения, среда выполнения D3D, DXGKernel, KMD и текущая работа задействуют ЦП с четырьмя потоками. Поток 0 выполняет большую часть работы. Потоки 1—3 практически не используются: в них попадают только логика приложения и среда выполнения D3D 11, создающая команды рендеринга. Драйвер пользовательского режима вообще не создает команд для этих потоков в силу особенностей устройства D3D 11.

    Профилирование в D3D12

    Image may be NSFW.
    Clik here to view.

    Рисунок 22. Здесь показана такая же нагрузка, как на рис. 21, но в D3D 12. Нагрузка равномерно распределяется по всем 4 потокам, а с учетом других мер по повышению эффективности в D3D 12 скорость выполнения нагрузки значительно увеличена

    Теперь рассмотрим такую же нагрузку в D3D 12 (рис. 22). Логика приложения, среда выполнения D3D, DXGKernel, KMD и текущая работа также задействуют ЦП с четырьмя потоками. Но здесь работа равномерно распределяется по всем потокам за счет оптимизации в D3D 12. Поскольку команды создаются параллельно, выполняемая среда D3D также работает параллельно. Издержки ядра значительно снижены за счет оптимизации ядра в WDDM 2.0. UMD работает во всех потоках, а не только в потоке 0, что означает настоящее распараллеливание создания команд. И наконец, наборы заменяют логику избыточного изменения состояния в D3D 11 и ускоряют работу логики приложения.

    Показатели D3D11 и D3D12

    Image may be NSFW.
    Clik here to view.

    Рисунок 23. Сравнение параллельной обработки в D3D 11 и D3D 12

    На рис. 23 показано сравнение обеих версий. Поскольку уровень фактической параллельности достаточно высок, мы видим относительно равное использование ЦП потоком 0 и потоками 1—3. Потоки 1—3 выполняют больше работы, поэтому в столбце «Только графика» видно увеличение. Кроме того, благодаря снижению нагрузки в потоке 0 и новым мерам по повышению эффективности среды выполнения и драйвера общую нагрузку на ЦП удалось снизить примерно на 50 %. Если рассмотреть столбец «Приложение плюс графика», здесь также распределение нагрузки между потоками стало более равномерным, а использование ЦП снизилось примерно на 32 %.

    9.0 Заключение

    В D3D 12 повышена эффективность использования ЦП за счет более крупных объектов состояния конвейера. Вместо того чтобы задавать и прочитывать каждое состояние по отдельности, разработчики получили единую точку приложения сил, тем самым полностью избавившись от издержек аппаратного несоответствия. Приложение задает PSO, а драйвер получает команды API и преобразует их в код ГП. Новая модель привязки ресурсов не имеет издержек, вызванных логикой управления потоком, которая теперь не нужна.

    За счет использования куч, таблиц и наборов D3D 12 обеспечивает более эффективное использование ЦП и более высокую масштабируемость. Вместо явных точек привязки используются управляемые приложением или игрой объекты памяти. Часто используемые команды можно записывать и многократно воспроизводить в одном кадре или в нескольких кадрах с помощью наборов. Списки команд и очередь команд позволяют параллельно создавать списки команд в нескольких потоках ЦП. Практически вся работа равномерно распределяется по всем потокам ЦП, что позволяет раскрыть весь потенциал и всю мощь процессоров Intel® Core™ 4-го и 5-го поколений.

    Direct3D 12 — значительный шаг в развитии технологий игр на ПК. Разработчики игр смогут работать «ближе к железу» за счет более компактного API и драйвера с меньшим количеством промежуточных уровней. За счет этого повышается эффективность и производительность. С помощью сотрудничества группа разработки D3D создала новый API и модель драйверов, предоставляющую разработчикам более широкие возможности управления, что позволяет создавать игры в полном соответствии с замыслом, с великолепной графикой и отличной производительностью.

    Ссылки и полезные материалы

    Ссылки на материалы Intel

    Корпоративный бренд: http://intelbrandcenter.tagworldwide.com/frames.cfm

    Наименования продуктов Intel®: http://www.intel.com/products/processor number/

     

    Уведомления и примечания

    См. http://legal.intel.com/Marketing/notices+and+disclaimers.htm

    Об авторе

    Майкл Коппок (Michael Coppock) работает в корпорации Intel с 1994 года, он специализируется на производительности графики и игр для ПК. Он помогает компаниям, разрабатывающим игры, наиболее эффективно задействовать все возможности ГП и ЦП Intel. Занимаясь и программным обеспечением, и оборудованием, Майкл работал со множеством продуктов Intel, начиная с процессора 486DX4 Overdrive.

    Примечания

    ИНФОРМАЦИЯ В ДАННОМ ДОКУМЕНТЕ ПРИВЕДЕНА ТОЛЬКО В ОТНОШЕНИИ ПРОДУКТОВ INTEL. ДАННЫЙ ДОКУМЕНТ НЕ ПРЕДОСТАВЛЯЕТ ЯВНОЙ ИЛИ ПОДРАЗУМЕВАЕМОЙ ЛИЦЕНЗИИ, ЛИШЕНИЯ ПРАВА ВОЗРАЖЕНИЯ ИЛИ ИНЫХ ПРАВ НА ИНТЕЛЛЕКТУАЛЬНУЮ СОБСТВЕННОСТЬ. КРОМЕ СЛУЧАЕВ, УКАЗАННЫХ В УСЛОВИЯХ И ПРАВИЛАХ ПРОДАЖИ ТАКИХ ПРОДУКТОВ, INTEL НЕ НЕСЕТ НИКАКОЙ ОТВЕТСТВЕННОСТИ И ОТКАЗЫВАЕТСЯ ОТ ЯВНЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ ГАРАНТИЙ В ОТНОШЕНИИ ПРОДАЖИ И/ИЛИ ИСПОЛЬЗОВАНИЯ СВОИХ ПРОДУКТОВ, ВКЛЮЧАЯ ОТВЕТСТВЕННОСТЬ ИЛИ ГАРАНТИИ ОТНОСИТЕЛЬНО ИХ ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ, ОБЕСПЕЧЕНИЯ ПРИБЫЛИ ИЛИ НАРУШЕНИЯ КАКИХ-ЛИБО ПАТЕНТОВ, АВТОРСКИХ ПРАВ ИЛИ ИНЫХ ПРАВ НА ИНТЕЛЛЕКТУАЛЬНУЮ СОБСТВЕННОСТЬ.

    КРОМЕ СЛУЧАЕВ, СОГЛАСОВАННЫХ INTEL В ПИСЬМЕННОЙ ФОРМЕ, ПРОДУКТЫ INTEL НЕ ПРЕДНАЗНАЧЕНЫ ДЛЯ ИСПОЛЬЗОВАНИЯ В СИТУАЦИЯХ, КОГДА ИХ НЕИСПРАВНОСТЬ МОЖЕТ ПРИВЕСТИ К ТРАВМАМ ИЛИ ЛЕТАЛЬНОМУ ИСХОДУ.

    Корпорация Intel оставляет за собой право вносить изменения в технические характеристики и описания своих продуктов без предварительного уведомления. Проектировщики не должны полагаться на отсутствующие характеристики, а также характеристики с пометками «Зарезервировано» или «Не определено». Эти характеристики резервируются Intel для будущего использования, поэтому отсутствие конфликтов совместимости для них не гарантируется. Информация в данном документе может быть изменена без предварительного уведомления. Не используйте эту информацию в окончательном варианте дизайна.

    Продукты, описанные в данном документе, могут содержать ошибки и неточности, из-за чего реальные характеристики продуктов могут отличаться от приведенных здесь. Уже выявленные ошибки могут быть предоставлены по запросу.

    Перед размещением заказа получите последние версии спецификаций в региональном офисе продаж Intel или у местного дистрибьютора.

    Копии документов с порядковым номером, ссылки на которые содержатся в этом документе, а также другую литературу Intel можно получить, позвонив по телефону 1-800-548-47-25 либо на сайте http://www.intel.com/design/literature.htm.

    Intel, эмблема Intel, Intel Atom и Intel Core являются товарными знаками корпорации Intel в США и в других странах.

    * Другие наименования и торговые марки могут быть собственностью третьих лиц.

    Intel, эмблема Intel, Intel Atom и Intel Core являются товарными знаками корпорации Intel в США и в других странах.

    * Другие наименования и торговые марки могут быть собственностью третьих лиц.

    © Корпорация Intel, 2014. Все права защищены.

     

    Уведомление об оптимизации

    Уведомление об оптимизации

    Компиляторы Intel могут не обеспечивать ту же степень оптимизации для других микропроцессоров (не корпо­рации Intel), даже если в них реализованы такие же возможности для оптимизации, как в микропроцессорах Intel. К ним относятся наборы команд SSE2®, SSE3 и SSSE3 и другие возможности для оптимизации. Корпорация Intel не гарантирует доступность, функциональность или эффективность какой-либо оптимизации на микро­процессорах других производителей. Микропроцессорная оптимизация, реализованная в этом продукте, пред­назначена только для использования с микропроцессорами Intel. Некоторые виды оптимизации, применя­емые не только для микроархитектуры Intel, зарезервированы для микропроцессоров Intel. Ознакомьтесь с руководством пользователя и справочным руководством по соответствующему продукту для получения более подробной информации о конкретных наборах команд, которых касается данное уведомление.

    Редакция уведомления № 20110804

    ПРИМЕЧАНИЕ.В зависимости от содержимого могут потребоваться дополнительные уведомления и примечания. Как правило, они находятся в следующих местах, и их необходимо добавить в раздел «Уведомления» соответствующих документов.

    Общие уведомления:уведомления, размещаемые во всех материалах, распространяемых и выпускаемых корпорацией Intel.

    Уведомления в отношении производительности и ее измерения:уведомления для материалов, используемых корпорацией Intel для измерения производительности или для заявлений о производительности.

    Сопутствующие технические уведомления:уведомления, которые следует добавлять в технические материалы Intel, описывающие внешний вид, пригодность или функциональность продукции Intel.

    Технические примечания:примечания к материалам Intel, когда описываются преимущества или возможности технологий и программ.

    Примечание для технических уведомлений: если все описываемые продукты (например, ACER ULV) обладают определенной функцией или поддерживают определенную технологию, то можно удалить заявление о требованиях в уведомлении. При наличии нескольких технических уведомлений можно объединить все заявления «фактическая производительность может различаться» в одно общее.

  • Microsoft Direct3D* 12
  • direct3d
  • D3D
  • Desarrolladores
  • Microsoft Windows* 8.x
  • Desarrollo de juegos
  • Windows*
  • Intermedio
  • Desarrollo de juegos
  • Dirección URL
  • Introducing Intel® Atom™ x3 (Code-Named “SoFIA”) SoC Processor Series

    Introduction

    On March 2, 2015, during the Mobile World Congress in Barcelona, Spain, one of the announcements Intel made was to introduce the Intel® Atom™ x3 Processor Series, Intel’s first integrated communication platform. Formerly code named “SoFIA”, Intel® Atom™ x3 Processor Series is a low-cost SoC with 64-bit Intel Atom processor cores and integrated cellular baseband modem for smart or feature phones, phablets, and tablets. The SoC will be available in 4G LTE and 3G versions.

    Intel® Atom™ x3 Processor Series provides a foundation for full-featured and cost-effective platforms with fast and seamless mobile experiences which meet today’s consumers’ expectations.

    This blog will go through the high level features of the Intel® Atom™ x3 platform, especially the features which mobile app developers are interested in.

    Please note that the processor series has not been officially released yet, information discussed in this blog post is subject to change without notice.

    The Intel® Atom™ x3 Processor Series includes 3 versions (SKUs):  the Intel® Atom™ x3-C3440 processor, the Intel® Atom™ x3-C3130 processor, and the Intel® Atom™ x3-C3230RK processor.

     

     Architectures and Specifications

    The Intel® Atom™ x3-C3440 processor includes a 64-bit quad-core Intel® Atom™ CPU and an integrated 4G LTE 5-band modem. The upgraded video can provide 1080p HD playback. The Mali T720 MP2 GPU supports Open GL ES 3.0 and DirectX 9.3. Figure 1 shows the Intel® Atom™ x3-C3440 processor high level box diagram.

    Image may be NSFW.
    Clik here to view.
    Figure 1The Intel® Atom™ x3-C3440 processor high level block diagram

                  Figure 1The Intel® Atom™ x3-C3440 processor high level block diagram

    Besides the C3440 version which supports the 4G LTE technologies, the Intel® Atom™ x3-C3130 processor series also includes 2 SKUs which support 3G mobile technologies:  the Intel® Atom™ x3-C3130 processor and the Intel® Atom™ x3-C3230RK processor, which provide low-cost options with performance.

    The Intel® Atom™ x3-C3130 processor features a 64-bit dual-core Intel® Atom™ CPU and an integrated 3G modem. Figure 2 shows its high level box diagram.

    Image may be NSFW.
    Clik here to view.
    Figure 2 The Intel® Atom™ x3-C3130 processor features a dual-core Intel Atom CPU and an integrated 3G modem.

            Figure 2 The Intel® Atom™ x3-C3130 processor features a dual-core Intel Atom CPU and an integrated 3G modem.

    The Intel® Atom™ x3-C3230RK processor, a collaboration between Intel and Rockchip*, includes a quad-core 64-bit Intel® Atom™ CPU and an integrated 3G modem. Figure 3 describes this SKU’s high level architecture.

    Image may be NSFW.
    Clik here to view.
    Figure 3 The Intel® Atom™ x3-C3230RK processor includes a quad-core Intel Atom CPU and an integrated 3G modem.

            Figure 3 The Intel® Atom™ x3-C3230RK processor includes a quad-core Intel Atom CPU and an integrated 3G modem. During Intel Developer Forum in Shenzhen, China on April 8, 2015, Intel and Rockchip* announced devices based on  the Intel® Atom™ x3-C3230RK processor are expected in market later in Q2, 2015

     

    On the graphics side, the Intel® Atom™ x3-C3130 processor includes a Mali* 400MP2 GPU, and the Intel® Atom™ x3-C3230RK processor includes a Mali* 450 MP4 GPU. Both processors support up to OpenGL ES 2.0.

    As a summary, Figure 4 shows a comparison table for the 3 Intel® Atom™ x3 processor SKUs.

     

    Image may be NSFW.
    Clik here to view.
    Figure 4 A comparison of the Intel® Atom™ x3 processor SKUs

            Figure 4 A comparison of the Intel® Atom™ x3 processor SKUs

    Feature Highlights

    High Performance SoC integration for great mobile user experiences

    The Intel Atom x3 processor series features 64-bit Intel Atom quad-core or dual-core IA processors at up to 1.4GHz Bust Mode, a fast 4G LTE or 3G integrated cellular baseband modem, HD video and quality audio, GPU, and the ISP module. The ISP supports dual cameras, including an up to 5MP front facing camera and up to 13MP rear-facing camera.

    Low-power RF and low-power video encoding / decoding result in a long battery life.

     

    Fast 4G LTE and 3G communications

    4G LTE and 3G Intel modems are interoperable with mobile network operators around the globe and support world-wide roaming. In the 4G LTE SKU, up to 14 LTE bands can be supported with the 5-mode LTE modem (2G, 3G, 4G LTE, FDD/TDD, and TD-SCDMA).

     

    Connectivity

    The Intel Atom x3 processor series supports a full range of connectivity capabilities which will keep the user always connected: Wi-Fi, Bluetooth, and GPS and GNSS. These capabilities enable various mobile use cases, from networking to location-based services.

    Impressive graphics and audio

    The GPU provides clear and responsive graphics for games, including supports for OpenGL ES 2.0 (the C3130 and C3230RK SKUs) and 3.0 (the C3440 SKU).  The platform supports high quality audio HD video media playback and Miracast-based wireless display.

    Value-added capacities

    The dual SIM capability enables mobile subscriptions from 2 different service providers / carriers. As an option on the C3440 SKU, Near Field Communication (NFC) supports streamlined and secure tap-and-pay transactions.

    Summary

    In the above discussion, we can see the Intel® Atom™ x3 Processor Series integrates high performance Intel® Atom™ CPU cores and a fast communication modem on a single SoC silicon. It provides a quality foundation for entry and value tablets, phablets, and smartphones affordable for consumers around the world. 

     

     

    References

    http://newsroom.intel.com/community/intel_newsroom/blog/2015/03/02/intel-launches-new-mobile-socs-lte-solution

    http://www.intel.com/content/www/us/en/processors/atom/atom-x3-c3000-brief.html

    *Other names and brands may be claimed as the property of others.

     

  • Intel® Atom™ processor
  • Android
  • Android Smartphone
  • Android Tablets
  • Imagen del icono: 

    Image may be NSFW.
    Clik here to view.

    Adjuntos: 

    https://software.intel.com/sites/default/files/managed/a2/fd/C3130.jpg
    https://software.intel.com/sites/default/files/managed/a2/fd/C3230RK.jpg
    https://software.intel.com/sites/default/files/managed/a2/fd/C3440.jpg
    https://software.intel.com/sites/default/files/managed/a2/fd/Specification.jpg
  • Procesadores Intel® Atom™
  • Experiencia del usuario y diseño
  • Android*
  • Windows*
  • Teléfono
  • Equipo Tableta
  • Desarrolladores
  • Socios
  • Profesores
  • Estudiantes
  • Android*
  • Microsoft Windows* 10
  • Incluir en RSS: 

    1
  • Principiante
  • Intermedio
  • Exploring Air Quality Monitoring Using Intel® Edison

    Air quality monitoring is an interesting topic to explore with the rises in pollution, allergy sensitivity, awareness of health & fitness, and technology innovation. The consumer marketplace has seen innovative products released bringing more awareness to air quality monitoring in the home. One such product is the smart scale. These smart scales monitor a variety of health related parameters and also the air quality. The air quality is sent to the cloud and an app can alert you to the changes in the air quality so you will know when an area needs ventilation with fresh air. Having an awareness of the air quality could allow for an improved quality of life. This article shows a method of exploring air quality monitoring by measuring carbon dioxide, volatile organic compounds (VOC), and dust levels using the Arduino* ecosystem and sending the data to a cloud service provider.

    The Intel® Edison platform is a natural fit for starting a new prototype or migrating an existing one given its fast processor, large memory size, and integrated connectivity for WiFi and Bluetooth. The Arduino ecosystem provides a capable set of hardware and firmware libraries to experiment with using the Intel® Edison Compute Module and Intel® Edison Arduino Breakout Board.

    To learn more about the Intel Edison platform, please see the link below:

    http://www.intel.com/content/www/us/en/do-it-yourself/edison.html

    Hardware Components:

    This project uses the following hardware components for the air quality monitoring system:

    • Intel® Edison Compute Module
    • Intel® Edison Arduino Breakout Board
    • Common Cathode RGB LED + 3 x 1kΩ resistors
    • GP2Y1010AU0F Optical Dust Sensor + 150Ω resistor + 220 µF electrolytic capacitor
    • MQ-135 Gas Sensor
    • K-30 CO2 Sensor
    • PIR Motion Sensor

    Image may be NSFW.
    Clik here to view.

    Figure 1 - Hardware Diagram

    Theory of Operation:

    Figure 1 shows the hardware component connections to the Intel® Edison Arduino Breakout Board. The system uses an RGB LED as a simple visual indication system for displaying the air quality.

    To determine the total air quality of an area, three sensors are used:

    1. An optical dust sensor is used to measure the dust in the area.

    2. A gas sensor is used to measure the Volatile Organic Compounds (VOC) such as smoke.

    3.  A CO2 sensor is used to measure the carbon dioxide levels with an I2C interface.

    In addition, a motion sensor is used for helping the system get the best representation of the total air quality in an area, by filtering out temporary increases in dust concentration caused by movement, and temporary increases in CO2 concentration caused by a person breathing close to the sensors.

    When there is no motion detected, the firmware reads the air quality sensors, analyzes the sensor data, updates the visual indication system, and sends the air quality data to the cloud. The details of the system are further discussed in the Firmware section.

    To learn more about the sensors, please see the data sheets at the links below:

    http://www.kosmodrom.com.ua/pdf/MQ135.pdf

    https://www.sparkfun.com/datasheets/Sensors/gp2y1010au_e.pdf

    http://www.co2meter.com/collections/co2-sensors/products/k-30-co2-sensor-module

    http://www.ladyada.net/media/sensors/PIRSensor-V1.2.pdf

    Configuring the I2C Clock Frequency:

    It is important to note that at the time of this writing, the default I2C clock frequency on Intel® Edison is above 100kHZ which is outside the specification of the K-30 CO2 sensor. The K-30 CO2 sensor supports a maximum I2C clock frequency (SCL) of 100kHz. The Intel® Edison I2C clock frequency can be changed to 100kHZ following a few steps:

    -Ensure that the latest Intel® Edison Yocto firmware image is installed:

    http://www.intel.com/support/edison/sb/CS-035180.htm

    -Open an Edison Linux terminal and login as root:

    https://software.intel.com/en-us/articles/getting-started-with-the-intel-edison-board-on-windows

    -cd /sys/devices/pci0000:00/0000:00:09.1/i2c_dw_sysnode

    -echo std > mode

    -cat mode

    To learn more about the Intel® Edison compute module and the I2C peripheral, please see the link below:

    http://www.intel.com/support/edison/sb/CS-035274.htm?wapkw=intel+edison+compute+module+hardware+guide

     

    Firmware:

    The following code shows the includes, macros, and functions for the air quality system. Functions for Initialization, Main Loop, Reading Motion Sensor, Reading Air Quality Sensors, Analyzing Total Air Quality, Updating Visual Indication LED, and Sending Data to a Cloud Service Provider are discussed.

    Includes:

    #include <Wire.h>

    Macros:

    //Pin Defines
    #define gasSensorPin A1
    #define dustSensorPin A0
    #define dustSensorLEDPin 2
    #define redRGBLEDPin 3
    #define greenRGBLEDPin 4
    #define blueRGBLEDPin 5
    #define motionSensorPin 6
    
    //Air Quality Defines
    #define AIR_QUALITY_OPTIMAL 2
    #define AIR_QUALITY_GOOD    1
    #define AIR_QUALITY_BAD     0
    #define AIR_QUALITY_UNKNOWN -1
    #define MAX_SENSOR_READINGS        10
    #define SENSOR_READING_DELAY 1000
    
    //Motion Sensor Defines 
    #define MOTION_NOT_DETECTED 0
    #define MOTION_DETECTED     1
    #define MOTION_DELAY_TIME   1000
    
    //Dust Sensor Timing Parameters (from p.5 of datasheet)
    #define SAMPLE_DELAY        280  //Sampling
    #define PULSEWIDTH_DELAY    40   //Pw
    #define PERIOD_DELAY        9680 //T
    
    //Gas Sensor Thresholds
    #define GAS_SENSOR_OPTIMAL 140
    #define GAS_SENSOR_GOOD    200
    
    //Dust Sensor Thresholds
    #define DUST_SENSOR_OPTIMAL 125
    #define DUST_SENSOR_GOOD    250
    
    //CO2 Sensor Thresholds
    #define CO2_SENSOR_OPTIMAL 800
    #define CO2_SENSOR_GOOD    2000
    

    Functions:

    Initialization: This function initializes the serial debug interface, the I/O pins, and the I2C interface.

    void setup() {
      Serial.begin(9600);
      pinMode(gasSensorPin, INPUT);
      pinMode(dustSensorPin, INPUT);
      pinMode(dustSensorLEDPin, OUTPUT);
      pinMode(redRGBLEDPin, OUTPUT);
      pinMode(greenRGBLEDPin, OUTPUT);
      pinMode(blueRGBLEDPin, OUTPUT);
      pinMode(motionSensorPin, INPUT);
      Wire.begin();
    }
    

    Main Loop: The main loop initializes the system, checks for motion, reads the air quality sensors, analyzes the total air quality, updates the indication LED, and sends the data to a cloud service.

    void loop() {
      // -- Init
      int airQuality = 0;
      int motion = 0;
      int sensorAirQuality[3] = {0,0,0}; //0-Gas Sensor, 1-CO2 Sensor, 2-DustSensor
      Serial.println("");
     
      // -- Check for motion
      motion = readMotionSensor();
     
      if (motion == MOTION_NOT_DETECTED) {
        // -- Read Air Quality Sensors
        readAirQualitySensors(sensorAirQuality);
       
        // -- Analyze Total Air Quality
        airQuality = analyzeTotalAirQuality(sensorAirQuality[0],sensorAirQuality[1],sensorAirQuality[2]);
       
        // -- Update Indication LED
        updateIndicationLED(airQuality);
       
        // -- Update Air Quality Value for Cloud Datastream
        updateCloudDatastreamValue(CHANNEL_AIR_QUALITY_ID, airQuality);
     
        // -- Send Data To Cloud Service
        sendToCloudService();
      }
    }
    

    Reading Motion Sensor: The motion sensor is read by sampling the sensor’s digital output pin. If motion is detected, the sensor output pin will go HIGH. The function attempts to filter glitches and returns whether motion was detected or not.

    int readMotionSensor() {
      // -- Init
      int motionSensorValue = MOTION_NOT_DETECTED;
      int motion = MOTION_NOT_DETECTED;
     
      Serial.println("-Read Motion Sensor");
     
      // -- Read Sensor
      motionSensorValue = digitalRead(motionSensorPin);
     
      // -- Analyze Value
      if (motionSensorValue == MOTION_DETECTED) {
        delay(MOTION_DELAY_TIME); 
        motionSensorValue = digitalRead(motionSensorPin);
       
        if (motionSensorValue == MOTION_DETECTED) {
          motion = MOTION_DETECTED;
          Serial.println("--Motion Detected");
          updateIndicationLED(AIR_QUALITY_UNKNOWN);
        }
      }
      return motion;
    }
    

    Reading Air Quality Sensors: This function calls the individual gas, co2, and dust sensor functions. The function takes a pointer to integer array for storing the air quality results for each sensor.

    void readAirQualitySensors(int* sensorAirQuality)
    {
      Serial.println("-Read Air Quality Sensors");
     
      sensorAirQuality[0] = readGasSensor();
      sensorAirQuality[1] = readCO2Sensor();
      sensorAirQuality[2] = readDustSensor();
    }
    

    Reading Gas Sensor: The gas sensor can detect gases such as NH3, NOx, alcohol, Benzene, and smoke. The gas sensor contains an analog voltage output that is proportional to the gas levels in the air. An A/D conversion is performed to read this sensor. The function reads the sensor, averages the readings, analyzes the sensor data, and returns the air quality for this sensor.

    int readGasSensor() {
      // -- Init
      int airQuality = 0;
      int gasSensorValue = 0;
     
      // -- Read Sensor
      for (int i=0; i < MAX_SENSOR_READINGS; i++) {
        gasSensorValue += analogRead(gasSensorPin);
        delay(SENSOR_READING_DELAY);
      }
      gasSensorValue /= MAX_SENSOR_READINGS; //Average the sensor readings
     
      // -- Update Cloud Datastream
      Serial.print("--gasSensorValue = ");
      Serial.println(gasSensorValue);
      updateCloudDatastreamValue(CHANNEL_GAS_SENSOR_ID, gasSensorValue);
     
      // -- Analyze Value
      if (gasSensorValue < GAS_SENSOR_OPTIMAL) {
        airQuality = AIR_QUALITY_OPTIMAL;
      }
      else if (gasSensorValue < GAS_SENSOR_GOOD) {
        airQuality = AIR_QUALITY_GOOD;
      }
      else {
        airQuality = AIR_QUALITY_BAD;
      }
    
      return airQuality;
    }
    

    Reading Dust Sensor: The dust sensor contains an optical sensing system that is energized using a digital output pin. An A/D conversion is then performed to sample the sensor’s analog voltage output that is proportional to the dust in the air. This function reads the sensor, averages the readings, analyzes the sensor data, and returns the air quality for this sensor.

    int readDustSensor() {
      // -- Init
      int airQuality = 0;
      int dustSensorValue = 0;
     
     
      // -- Read Sensor
      for (int i=0; i < MAX_SENSOR_READINGS; i++) {
        digitalWrite(dustSensorLEDPin,LOW);  //Enable LED
        delayMicroseconds(SAMPLE_DELAY);
        dustSensorValue += analogRead(dustSensorPin);
        delayMicroseconds(PULSEWIDTH_DELAY);
        digitalWrite(dustSensorLEDPin,HIGH); //Disable LED
        delayMicroseconds(PERIOD_DELAY);
        delay(SENSOR_READING_DELAY);
      }
      dustSensorValue /= MAX_SENSOR_READINGS; //Average the sensor readings
     
      // -- Update Cloud Datastream
      Serial.print("--dustSensorValue = ");
      Serial.println(dustSensorValue);
      updateCloudDatastreamValue(CHANNEL_DUST_SENSOR_ID, dustSensorValue);
     
      // -- Analyze Value
      if (dustSensorValue < DUST_SENSOR_OPTIMAL) {
        airQuality = AIR_QUALITY_OPTIMAL;
      }
      else if (dustSensorValue < DUST_SENSOR_GOOD) {
        airQuality = AIR_QUALITY_GOOD;
      }
      else {
        airQuality = AIR_QUALITY_BAD;
      } 
     
      return airQuality;
    }
    

    Reading CO2 Sensor: The CO2 sensor returns a CO2 concentration level in parts per million (ppm). The CO2 sensor is read through the I2C interface. This function reads the sensor, averages the readings, analyzes the sensor data, and returns the air quality for this sensor.

    int readCO2Sensor() {
      // -- Init
      int airQuality = 0;
      int co2SensorValue = 0;
      int tempValue=0;
      int invalidCount=0;
     
      // -- Read Sensor
      for (int i=0; i < MAX_SENSOR_READINGS; i++) {
        tempValue = readCO2();  // see http://cdn.shopify.com/s/files/1/0019/5952/files/Senseair-Arduino.pdf?1264294173 for this function
        (tempValue == 0) ? invalidCount++ : co2SensorValue += tempValue;
        delay(SENSOR_READING_DELAY);
      }
     
      if (invalidCount != MAX_SENSOR_READINGS) {
        co2SensorValue /= (MAX_SENSOR_READINGS - invalidCount); //Average the sensor readings
      }
     
      // -- Update Cloud Datastream
      Serial.print("--co2SensorValue = ");
      Serial.println(co2SensorValue);
      updateCloudDatastreamValue(CHANNEL_CO2_SENSOR_ID, co2SensorValue);
     
      // -- Analyze Value
      if (co2SensorValue < CO2_SENSOR_OPTIMAL) {
        airQuality = AIR_QUALITY_OPTIMAL;
      }
      else if (co2SensorValue < CO2_SENSOR_GOOD) {
        airQuality = AIR_QUALITY_GOOD;
      }
      else {
        airQuality = AIR_QUALITY_BAD;
      } 
     
      return airQuality;
    }
    

    Analyzing Total Air Quality: This function determines the total air quality for the area by analyzing the gas, co2, and dust air quality values passed to this function. The function returns the total air quality level for the area.

    int analyzeTotalAirQuality(int gasAirQuality, int co2AirQuality, int dustAirQuality) {
        int airQuality = 0;
        Serial.println("-Analyze Total Air Quality");
        if (gasAirQuality==AIR_QUALITY_BAD    \
            || dustAirQuality==AIR_QUALITY_BAD \
            || co2AirQuality==AIR_QUALITY_BAD) {
          Serial.println("--Air Quality Is BAD");
          airQuality = AIR_QUALITY_BAD;
        }
        else if (gasAirQuality == AIR_QUALITY_OPTIMAL \
                 && dustAirQuality == AIR_QUALITY_OPTIMAL \
                 && co2AirQuality==AIR_QUALITY_OPTIMAL) {
          Serial.println("--Air Quality Is OPTIMAL");
          airQuality = AIR_QUALITY_OPTIMAL;
        }
        else  {
          Serial.println("--Air Quality Is Good");
          airQuality = AIR_QUALITY_GOOD;
        }
        return airQuality;
    }
    

    Updating Visual Indication LED: This function updates the indication LED to the appropriate color for the air quality value that is passed to this function. The LED turns blue for optimal air quality levels, green for good air quality levels, and red for bad air quality levels. The LED turns magenta if motion is detected.

    void updateIndicationLED(int airQuality) {
      Serial.println("-Update Indication LED");
      // --Turn off all colors
      digitalWrite(redRGBLEDPin,LOW);
      digitalWrite(greenRGBLEDPin,LOW);
      digitalWrite(blueRGBLEDPin,LOW);
         
      // --Update Indication LED
      if (airQuality == AIR_QUALITY_UNKNOWN) {
        digitalWrite(redRGBLEDPin,HIGH);
        digitalWrite(greenRGBLEDPin,HIGH);
        digitalWrite(blueRGBLEDPin,HIGH);
      }
      else if (airQuality == AIR_QUALITY_OPTIMAL) {
        digitalWrite(blueRGBLEDPin, HIGH);
      }
      else if (airQuality == AIR_QUALITY_GOOD) {
        digitalWrite(greenRGBLEDPin, HIGH);
      }
      else {
        digitalWrite(redRGBLEDPin, HIGH);
      }
    }
    

    Sending Data to a Cloud Service Provider:

    To connect Intel® Edison to a WiFi network, please see the link below:

    http://www.intel.com/support/edison/sb/CS-035342.htm

    Image may be NSFW.
    Clik here to view.

    Figure 2 - xively.com feed

    In this example, xively.com is used as the cloud service provider that the air quality data is sent to. Figure 2 shows an example feed with four channels. The channels are further discussed in the Functions section. Integration with xively.com requires the Http Client and Xively libraries added to the Arduino IDE. Please see the link below to learn more about xively.com, creating an account, Arduino tutorials, and library integration with the Arduino IDE.

    https://xively.com/dev/tutorials/arduino_wi-fi/

    The following code shows an example of the includes, macros, and functions that can be added to the air quality system to add xively.com support.

    Includes:

    #include <WiFi.h>
    #include <HttpClient.h>
    #include <Xively.h>

    Macros:

    //Xively.com Defines
    #define XIVELY_FEED <enter your feed number here>
    #define XIVELY_KEY <enter your key string here>
    #define XIVELY_HTTP_SUCCESS 200
    #define CHANNEL_AIR_QUALITY "AIR_QUALITY"
    #define CHANNEL_AIR_QUALITY_ID    0
    #define CHANNEL_GAS_SENSOR "GAS_SENSOR"
    #define CHANNEL_GAS_SENSOR_ID     1
    #define CHANNEL_CO2_SENSOR "CO2_SENSOR"
    #define CHANNEL_CO2_SENSOR_ID     2
    #define CHANNEL_DUST_SENSOR "DUST_SENSOR"
    #define CHANNEL_DUST_SENSOR_ID    3
    #define MAX_CHANNELS              4
    

    Global Variables:

    //Xively Datastream
    XivelyDatastream datastreams[] = {
        XivelyDatastream(CHANNEL_AIR_QUALITY, strlen(CHANNEL_AIR_QUALITY), DATASTREAM_FLOAT),
        XivelyDatastream(CHANNEL_GAS_SENSOR, strlen(CHANNEL_GAS_SENSOR), DATASTREAM_FLOAT),
        XivelyDatastream(CHANNEL_CO2_SENSOR, strlen(CHANNEL_CO2_SENSOR), DATASTREAM_FLOAT),
        XivelyDatastream(CHANNEL_DUST_SENSOR, strlen(CHANNEL_DUST_SENSOR), DATASTREAM_FLOAT)
      };
    
    //Xively Feed
    XivelyFeed feed(XIVELY_FEED, datastreams, MAX_CHANNELS);
     
    //Xively Client
    WiFiClient client;
    XivelyClient xivelyclient(client);
    

    Functions:

    Updating the data stream: This function is called to update the values for a xively.com channel datastream. The function is passed the channelID, and the datastream value. In this system as shown in Figure 2, four datastreams are used. The datastreams are updated with raw sensor data from the gas, co2, and dust sensor functions. In addition, a datastream is also updated in the main loop with the total air quality value.

    void updateCloudDatastreamValue(int channelID, int value) {
      // -- Update the Datastream Value
      datastreams[channelID].setFloat(value);
    }
    

    Sending the Datastreams to Xively: This function performs a PUT operation to a xively.com feed. The function returns the status of successful or the error code. The main loop calls this function.

    void sendToCloudService() {
      int status=0;
      Serial.println("-Send To Cloud Service”);
    
      // -- Upload the Datastream to Xively
      status = xivelyclient.put(feed, XIVELY_KEY);
     
      // -- Verify Transaction
      if (status == XIVELY_HTTP_SUCCESS) {
       Serial.println("--HTTP OK");
      }
      else {
        Serial.print("--ERROR: ");
        Serial.println(status);
      }
    }
    

    Summary:

    Hope you enjoyed exploring air quality monitoring with the Intel Edison platform. Challenge yourself to add additional indication showing the status of each sensor, to add enhancements to the cloud service experience with alert triggers when the air quality changes, and also look for opportunities to integrate air quality monitoring with other systems.

    Image may be NSFW.
    Clik here to view.

    About the Author:

    Mike Rylee is a Software Engineer at Intel Corporation with a background in developing embedded systems and apps on Android*, Windows*, iOS*, and Mac*. He currently works on enabling for Android and the Internet of Things.

    ++This sample source code is released under the Intel Sample Source License

    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 and the Intel logo 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

    © 2015 Intel Corporation.

  • Desarrolladores
  • Estudiantes
  • Arduino
  • Yocto Project
  • Internet de las cosas
  • C/C++
  • Intermedio
  • Internet de las cosas
  • Sensores
  • Sistemas integrados
  • Contrato de licencia: 

  • Dirección URL

  • Using the Unity* Toolkit’s SendMessage Action with Intel® RealSense™ Technology

    The Unity Toolkit for Intel® RealSense™ technology  is a standard Unity package. It contains all the DLLs and scripts that are needed to use the Intel RealSense SDK in a Unity game or application. The toolkit allows for ease of use by making scripting properties available in the Inspector without the need to do much of the boilerplate coding required in the previous version of the SDK, the Intel® Perceptual Computing SDK.

    Purpose

    The purpose of this tutorial is to show you how to use the Unity Toolkit’s SendMessage action.  The SendMessage action allows you to call a function from another script whenever an Intel RealSense application event is triggered. This can be very useful when you want to use functionality from a different script than what is included in any of the action scripts.

    What this Tutorial Covers

    This tutorial will cover the steps needed to use the SendMessageAction action.

    Assumptions

    You must have read the sdktoolkit.pdf file, which is installed in the \RSSDK\doc folder. This document gives you a general idea how the Unity add-on works. This tutorial also assumes that you have some basic Unity skills such as importing an external package, adding a cube onto a scene, and applying a script to a game object.  

    Requirements

    Unity Professional 4.1 or higher.

    An Intel® RealSense™ 3D camera either embedded in a device or an external camera.

    Let’s Begin

    Import the Visual Studio* Plugin (Optional)

    While this step is not required, I prefer to use Visual Studio as my IDE. If you would like to use this free plugin, you can download it here http://unityvs.com/.

    Image may be NSFW.
    Clik here to view.
    Import the Visual Studio* Plugin (Optional)

    Import the Unity* package for Intel® RealSense™ Technology

    This package contains everything you need to set up and run Intel RealSense applications. The Unity package is located in the RSSDK\Framework\Unity folder. If you installed the Intel RealSense SDK in the default location, the RSSDK folder is in C:\Program Files (x86).

    Image may be NSFW.
    Clik here to view.
    Import the Unity* package for Intel® RealSense™ Technology

    You can import the Unity Toolkit as you would any package. When doing so, you have the options to pick and choose what components you want to use. For the purpose of this tutorial, we will use the defaults and import everything.

    As you can see in the following image, there are now several new items under the Assets folder.

    • Plugins and Plugins.Managed contain DLLs required for using the Intel RealSense SDK.
    • RSUnityToolkit folder contains all the scripts and assets for running the toolkit.

    We won’t go into what all the folders are and what they contain here as that is out of the scope of this tutorial.

    Image may be NSFW.
    Clik here to view.
    Assets RSUnityToolkit

    Game Objects

    Add a 3D cube to the scene.

    Image may be NSFW.
    Clik here to view.
    Game Objects 3D cube

    Add a Directional light to give the ship some light so you can see your game object better. 

    Image may be NSFW.
    Clik here to view.
    Game object directional light

    Scripting

    To make sure the SendMessageAction action works properly on a game object, you first need to drag and drop the SendMessageAction script onto the game object. Second, you need to create a new script that will contain a function that you want to be called whenever an Intel RealSense SDK action has been triggered.

    Create a new folder, then create a new script

    To keep things organized, I created a new folder to hold my custom script. Inside that folder, I created a new C# script called MyRotateScript. Inside this script I set up a function that will rotate the cube along the X axis at a set interval.

    Image may be NSFW.
    Clik here to view.
    MyCustomScripts MyRotateScript

    Open the script for editing

    Clear out any existing functions as they won’t be needed. Your script should look like this:

    Image may be NSFW.
    Clik here to view.
    MyRotateScript editing

    Next add the following code to your script:

    Image may be NSFW.
    Clik here to view.
    MyRotateScript Add Code

    Any time this function is called, the cube is rotated 30 degrees on each axis.
     

    Once you have saved your script, return to Unity and drag and drop this new script onto your cube game object. You won’t need to worry about editing this script in the Inspector. However, it is important that you add this script to your cube game object. The SendMessageScript relies on the fact that this script is attached to the same game object.

    Add the SendMessageAction script

    Grab the SendMessageAction script and drop it onto the cube.

    Image may be NSFW.
    Clik here to view.
    SendMessageAction script

    At this point in the Inspector you should see the two scripts, the MyRotateScript we just created and the SendMessageAction script.

    Image may be NSFW.
    Clik here to view.
    MyRotateScript SendMessageAction script

    Configure the Send Message Action script to call the rotation scripts RotateMyCube()

    On the Add Trigger button, select Event Source.

    Image may be NSFW.
    Clik here to view.
    RotateMyCube - Add Trigger - Event Source

    On the Event Source Add button, I have chosen Hand Detected. This is probably the easiest way to get this up and working.

    Image may be NSFW.
    Clik here to view.
    Send Message Action Script - Hand Detected

    Next choose the hand options. I have chosen Right hand. What this will do is that any time the camera sees my hand it will enable the Send Message Action.

    Image may be NSFW.
    Clik here to view.
    Send Message Action (Scrpt) - Access Order - Right Hands

    Under Function Name enter the name of the public function RotateMyCube, which resides in the MyRotateScript class that was created earlier.

    Image may be NSFW.
    Clik here to view.
    RotateMyCube - MyRotateScript

    One thing to note, the event fires only when the SDK detects your hand, and only one message is sent at a time. So, to see the cube rotate more than once, you must move your hand out of the camera’s view and bring it back.

     

    Congratulations, at this point, everything is ready to go.

    Save your scene,

    Save your project,

    and run the application you just created!

     

  • Intel RealSense
  • unity
  • Desarrolladores
  • Microsoft Windows* 10
  • Microsoft Windows* 8.x
  • Tecnología Intel® RealSense™
  • Unidad
  • Principiante
  • Intermedio
  • Tecnología Intel® RealSense™
  • Desarrollo de juegos
  • Portátil
  • Equipo Tableta
  • Escritorio
  • Dirección URL
  • Tecnología Intel® RealSense™
  • Intel AMT and Java

    For all of you Java developers out there that have be searching for tools to help with your Intel® Active Management Technology solutions, your search is over. I’d like to introduce you to the Intel® WS-Management Java Client Library, available for download here.

    This download contains source code for a library that can be used to make WS-Management calls to Intel® AMT devices. Also included are code samples that demonstrate how to use the library to interact with many AMT features and documentation on the library & samples.

     Key Features

    • Allows Intel® AMT development in Java environments

    • 100% pure Java (no JNI or native code wrapping)

    • Supports Digest and Kerberos authentication

    • Library is packaged in a single .jar file with JavaDocs

    • Supports JDK5 and newer (JDK6 required for native Kerberos support)

    •  

     Getting Started

    Just include IntelWsmanLib.jar in your class path and you can start calling the API.  I wrote a few of the samples in the download using the NetBeans Integrated Development Environment. But you can use any Java capable environment as long as you include the jar file. Relevant objects are found in the intel.management.wsman Java package.

    The library is WS-Management compliant and not AMT specific or even AMT version specific. There are no WSDL files, XSD files, or MOF files needed.

     Writing Code

    Here are some snippets to give you an idea of how the code looks.

    First create a connection to a WS-Management Service as follows:

            import intel.management.wsman.*;

            connection = WsmanConnection.createConnection(<url>);

    Then use the resulting connection object to perform WS-Transfer, WS-Enumeration, or WS-Eventing operations using either digest or Kerberos credentials.

     For example, to get the AMT host name:

            ManagedReference ref = connection.newReference(“AMT_GeneralSettings”);

            ManagedInstance inst = ref.get();

            inst.GetProperty(“HostName”);

    Take a look at the sample code included in the download for more details.

    Please post to our forum any questions, comments or feedback.

  • AMTJAVA
  • Imagen del icono: 

    Image may be NSFW.
    Clik here to view.
  • Tecnología Intel® vPro™
  • Seguridad
  • Tecnología Intel® Active Management
  • Cliente empresarial
  • Desarrolladores
  • Incluir en RSS: 

    0
  • Intermedio
  • Intel® XDK Update for April 2015, and Apache* Cordova*

    As you are probably aware, we did two updates in the past couple of weeks.  The March 30 update, build 1878, was a regular update to fix a number of open issues.  This one today, build 1912, is to address some regressions with that update.   Not what we had planned.  From all of us in the Intel® XDK team, our apologies for having to give you another update so quickly.  Fortunately, we do know exactly why and how the regressions happened and are correcting our development and testing processes appropriately.

    So, what’s in this update?

    • Bug-fixes – that’s it.  We fixed the Cordova* plugins regressions – selecting/unselecting the standard Cordova plugins and the intel.xdk plugins, a problem with selecting 3rd-party plugins, issues with ajax calls, and an issue with the Emulator giving a 404 error when it couldn’t find the index.html file.  There was also a firewall proxy problem a few users reported on OS X* that we fixed.  There were a few others, check the Release Notes to see if we fixed the problems you may have.  If you don’t see it there, please make sure you visit our user forums.
    • Also, we continued to improve the secure, single sign-on support we released earlier in March, allowing your Intel XDK login to work with the user forums on the Intel Developer Zone.  There were a few issues with non-English characters in user names that we resolved.

    Cordova* changes coming!

    Now, an important note about Apache* Cordova*.  We are a big fan, supporter, and contributor to the Apache Cordova project – it is doing a great service to mobile app developers in helping get access to native functionality in a standard way.  It also moves very fast, which is important given the rapidly changing nature of web development and web technologies.  As a tools vendor for HTML5 and one which views Cordova support as central to the core value of the product – the Intel XDK’s cross-platform support – we have to move very quickly as well to ensure we can offer new Cordova functionality as soon as it is ready.   It is challenging to stay up to date, but it is something we must do.

    Cordova 5.0 is being released this Summer.  It is a big change in that plugins will become node packages, adopting the NPM naming conventions, and the plugins registry will be going away as of this Fall.  App developers will need to be aware of the changes to how to integrate plugins, and the new names;  We intend to support 5.0 fully and will have releases in the Summer for it to continue to make it as easy as possible to add plugins into apps.  We’ll also be looking at ways to preview apps with plugins (coming soon!).  But, primarily, we want to make sure you are aware of the changes coming up so you can prepare.  Please let us know if you have any questions.  We’ll keep info on Cordova 5.0 on our user forums and website over the coming months.

    Please provide us feedback on our User Forum as to what or how you would like to see us help the Cordova project and your app development.

    We greatly appreciate your feedback and comments in the user forums and in private.  Please keep them coming!

    Joe

  • Intel XDK Cordova HTML5 Javascript Crosswalk
  • Imagen del icono: 

    Image may be NSFW.
    Clik here to view.
  • Herramientas de desarrollo
  • Intel® XDK
  • HTML5
  • JavaScript*
  • Android*
  • HTML5
  • Portátil
  • Teléfono
  • Equipo Tableta
  • Escritorio
  • Desarrolladores
  • Socios
  • Profesores
  • Estudiantes
  • Android*
  • Apple iOS*
  • Microsoft Windows* 10
  • Microsoft Windows* 8.x
  • Tizen*
  • Incluir en RSS: 

    1
  • Avanzado
  • Principiante
  • Intermedio
  • Use which hardware PMU events to calculate FLOPS on Intel(R) Xeon Phi(TM) coprocessor?

    FLOPS means total floating point operations per second, which is used in High Performance Computing. In general, Intel(R) VTune(TM) Amplifier XE
    only provides metric named Cycles Per Instruction (average CPI), that is to measure performance for general programs.

    In this article, I use matrix1.c as an example and show what events will be used to calculate FLOPS in code for different platform.
    First at all, I will use Intel(R) C++ compiler with different switchers to generate binary for legacy x87, SSE, AVX on Intel(R) Xeon
    processor, vector instructions on Intel(R) Xeon Phi(TM) coprocessor, then use events to calculate FLOPS.

    (I work on 2nd Generation Intel(R) Core(TM) Architecture, Sandy Bridge processor, CPUfrequency is 3.4 GHz, 64bit operation system)
    (I also work on Intel Xeon Phi coprocessor, CPU frequency is 1.09GHz)

    1. Use X87 OPS as traditional FP to generate legacy X87 instructions used, calculate FLOPS

    Build:
    gcc -g –mno-sse matrix1.c -o matrix1.x87

    Run VTune:
    amplxe-cl -collect-with runsa -knob event-config=FP_COMP_OPS_EXE.X87:sa=10000 -- ./matrix1.x87

    amplxe-cl –report hw-events

    Function Module Hardware Event Count:CPU_CLK_UNHALTED.REF_TSC (K) Hardware Event Count:FP_COMP_OPS_EXE.X87 (K)
    ----------------------- ----------- ------------------------------------------------- --------------------------------------------
    multiply matrix1.x87 36,782,055 2,160,570

    There were 2,160,570,000 counts of FP_COMP_OPS_EXE.X87
    Elapsed time of multiply() = 36,782,055,000 / 3,400,000,000 = 10.818 seconds
    FLOPS = 2,160,570,000 / 1,000,000 / 10.818 = 199.719 Mflops

    2. Use SSE registers by using Intel C++ compiler with SSE enabled options, calculate FLOPS

    Build:
    icc –g –fno-inline –xSSE4.1 matrix1.c –o matrix1.SSE41

    Run VTune:
    amplxe-cl -collect-with runsa -knob event-config=FP_COMP_OPS_EXE.X87:sa=10000 -- ./matrix1.SSE41

    amplxe-cl –collect-with runsa -knob event-config= FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE:sa=10000, FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE:sa=10000 -- ./matrix1.SSE41

    amplxe-cl –report hw-events

    Function Module Hardware Event Count:CPU_CLK_UNHALTED.REF_TSC (K) Hardware Event Count:FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE (K) Hardware Event Count:FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE (K)
    ---------------------------- ------------- ------------------------------------------------- ---------------------------------------------------------- ----------------------------------------------------------
    multiply matrix1.SSE41 1,100,002 0 1,185,800

    There were 1,185,800,000 counts of COMP_OPS_EXE.SSE_PACKED_DOUBLE
    Elapsed time of multiply() = 1,100,002,000 / 3,400,000,000 = 0.3235s
    FLOPS = 1,185,800,000 / 1,000,000 / 0.3235 = 3665.53 Mflops

    3. Use AVX registers by using Intel C++ compiler with the option to enable AVX, calculate FLOPS

    Build:
    icc -g -fno-inline -xAVX matrix1.c -o matrix1.AVX

    Run VTune:
    amplxe-cl -collect-with runsa -knob event-config=SIMD_FP_256.PACKED_DOUBLE:sa=10000 -- ./matrix1.AVX

    amplxe-cl –report hw-events
    Function Module Hardware Event Count:CPU_CLK_UNHALTED.REF_TSC (K) Hardware Event Count:SIMD_FP_256.PACKED_DOUBLE (K)
    ------------- ----------- ------------------------------------------------- --------------------------------------------------
    multiply matrix1.AVX 1,486,002 777,070

    There were 777,070,000 counts of SIMD_FP_256.PACKED_DOUBLE
    Elapsed time of multiply() = 1,486,002,000 / 3,400,000,000 = 0.437s
    FLOPS = 777,070,000 / 1,000,000 / 0.437 = 1778.19 Mflops

    4. Use vector instructions by using Intel C++ compiler to build native program for Intel Xeon Phi coprocessor, calculate FLOPS
    Build:
    icc -g -fno-inline -mmic -O3 matrix1.c -o matrix1.MIC

    FP operations of application will be processed via the vector processing unit (VPU), which provides data parallelism, VTune provides supported events:
    VPU_DATA_READ
    VPU_DATA_WRITE

    Run VTune:
    amplxe-cl -target-system=mic-native:0 -collect-with runsa -knob event-config=VPU_DATA_READ,VPU_DATA_WRITE -search-dir=. -- /root/matrix1.MIC

    amplxe-cl -R hw-events
    Function Module Hardware Event Count:VPU_DATA_READ (M) Hardware Event Count:VPU_DATA_WRITE (M) Hardware Event Count:CPU_CLK_UNHALTED (M)
    ---------------- ------------------ -------------------------------------- --------------------------------------- -----------------------------------------
    multiply matrix1.MIC 176 134 2,152

    There were (176+134)=300M counts of VPU_DAT_READ & VPU_DATA_WRITE
    Elapsed time of multiply() = 2,152,000,000 / 1,090,000,000 = 1.974s
    FLOPS = 300,000,000 / 1,000,000 / 1.974 = 151.97 Mflops

    Please note that my example is a single thread app working on one core, and you may develop multithreaded app working on multiple cores of Intel Xeon Phi coprocessor.

  • VTune Xeon Phi vector instruction performance metric
  • Imagen del icono: 

    Image may be NSFW.
    Clik here to view.

    Adjuntos: 

    https://software.intel.com/sites/default/files/managed/90/de/matrix1.c
  • Herramientas de desarrollo
  • Optimización
  • Vectorización
  • Amplificador Intel® VTune™
  • Intel® Advanced Vector Extensions
  • C/C++
  • Servidor
  • Escritorio
  • Desarrolladores
  • Estudiantes
  • Linux*
  • Incluir en RSS: 

    1
  • Intermedio
  • Null Pointer Dereferencing Causes Undefined Behavior

    I have unintentionally raised a large debate recently concerning the question if it is legal in C/C++ to use the &P->m_foo expression with P being a null pointer. The programmers' community divided into two camps. The first claimed with confidence that it wasn't legal while the others were as sure saying that it was. Both parties gave various arguments and links, and it occurred to me at some point that I had to make things clear. For that purpose, I contacted Microsoft MVP experts and Visual C++ Microsoft development team communicating through a closed mailing list. They helped me to prepare this article and now everyone interested is welcome to read it. For those who can't wait to learn the answer: That code is NOT correct.

    Image may be NSFW.
    Clik here to view.
    nullptr

    Debate history

    It all started with an article about a Linux kernel's check by the PVS-Studio analyzer. But the issue doesn't have to do anything with the check itself. The point is that in that article I cited the following fragment from Linux' code:

    static int podhd_try_init(struct usb_interface *interface,
            struct usb_line6_podhd *podhd)
    {
      int err;
      struct usb_line6 *line6 = &podhd->line6;
    
      if ((interface == NULL) || (podhd == NULL))
        return -ENODEV;
      ....
    }

    I called this code dangerous because I thought it to cause undefined behavior.

    After that, I got a pile of emails and comments, readers objecting to that idea of mine, and even was almost about to give in to their convincing arguments. For instance, as proof of that code being correct they pointed out the implementation of the offsetof macro, typically looking like this:

    #define offsetof(st, m) ((size_t)(&((st *)0)->m))

    We deal with null pointer dereferencing here, but the code still works well. There were also some other emails reasoning that since there had been no access by null pointer, there was no problem.

    Although I tend to be gullible, I still try to double-check any information I may doubt. I started investigating the subject and eventually wrote a small article: "Reflections on the Null Pointer Dereferencing Issue".

    Everything suggested that I had been right: One cannot write code like that. But I didn't manage to provide convincing proof for my conclusions and cite the relevant excerpts from the standard.

    After publishing that article, I again was bombarded by protesting emails, so I thought I should figure it all out once and for all. I addressed language experts with a question to find out their opinions. This article is a summary of their answers.

    About C

    The '&podhd->line6' expression is undefined behavior in the C language when 'podhd' is a null pointer.

    The C99 standard says the following about the '&' address-of operator (6.5.3.2 "Address and indirection operators"):

    The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.

    The expression 'podhd->line6' is clearly not a function designator, the result of a [] or * operator. It is an lvalue expression. However, when the 'podhd' pointer is NULL, the expression does not designate an object since 6.3.2.3 "Pointers" says:

    If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

    When "an lvalue does not designate an object when it is evaluated, the behavior is undefined" (C99 6.3.2.1 "Lvalues, arrays, and function designators"):

    An lvalue is an expression with an object type or an incomplete type other than void; if an lvalue does not designate an object when it is evaluated, the behavior is undefined.

    So, the same idea in brief:

    When -> was executed on the pointer, it evaluated to an lvalue where no object exists, and as a result the behavior is undefined.

    About C++

    In the C++ language, things are absolutely the same. The '&podhd->line6' expression is undefined behavior here when 'podhd' is a null pointer.

    The discussion at WG21 (232. Is indirection through a null pointer undefined behavior?), to which I referred to in the previous article, brings in some confusion. The programmers participating in it insist that this expression is not undefined behavior. However, no one has found any clause in the C++ standard permitting the use of "poldh->line6" with "polhd" being a null pointer.

    The "polhd" pointer fails the basic constraint (5.2.5/4, second bullet) that it must designate an object. No C++ object has nullptr as address.

    Summing it all up

    struct usb_line6 *line6 = &podhd->line6;

    This code is incorrect in both C and C++ when the podhd pointer equals 0. If the pointer equals 0, undefined behavior occurs.

    The program running well is pure luck. Undefined behavior may take different forms, including program execution in just the way the programmer expected. It's just one of the special cases of undefined behavior, and that's all.

    You cannot write code like that. The pointer must be checked before being dereferenced.

    Additional ideas and links

    • When considering the idiomatic implementation of the 'offsetof()' operator, one must take into account that a compiler implementation is permitted to use what would be non-portable techniques to implement its functionality. The fact that a compiler's library implementation uses the null pointer constant in its implementation of 'offsetof()' doesn't make it OK for user code to use '&podhd->line6' when 'podhd' is a null pointer.
    • GCC can / does optimize assuming no undefined behavior ever occurs, and would remove the null checks here -- the Kernel compiles with a bunch of switches to tell the compiler not to do this. As an example, the experts refer to the article "What Every C Programmer Should Know About Undefined Behavior #2/3".
    • You may also find it interesting that a similar use of a null pointer was involved in a kernel exploit with the TUN/TAP driver. See "Fun with NULL pointers". The major difference that might cause some people to think the similarity doesn't apply is that in the TUN/TAP driver bug the structure field that the null pointer accessed was explicitly taken as a value to initialize a variable instead of simply having the address of the field taken. However, as far as standard C goes, taking the address of the field through a null pointer is still undefined behavior.
    • Is there any case when writing &P->m_foo where P == nullptr is OK? Yes, for example when it is an argument of the sizeof operator: sizeof(&P->m_foo).

    Acknowledgements

    This article has become possible thanks to the experts whose competence I can see no reason to doubt. I want to thank the following people for helping me in writing it:

    • Michael Burr is a C/C++ enthusiast who specializes in systems level and embedded software including Windows services, networking, and device drivers. He can often be found on the StackOverflow community answering questions about C and C++ (and occasionally fielding the easier C# questions). He has 6 Microsoft MVP awards for Visual C++.
    • Billy O'Neal is a (mostly) C++ developer and contributor to StackOverflow. He is a Microsoft Software Development Engineer on the Trustworthy Computing Team. He has worked at several security related places previously, including Malware Bytes and PreEmptive Solutions.
    • Giovanni Dicanio is a computer programmer, specialized in Windows operating system development. Giovanni wrote computer programming articles on C++, OpenGL and other programming subjects on Italian computer magazines. He contributed code to some open-source projects as well. Giovanni likes helping people solving C and C++ programming problems on Microsoft MSDN forums and recently on StackOverflow. He has 8 Microsoft MVP awards for Visual C++.
    • Gabriel Dos Reis is a Principal Software Development Engineer at Microsoft. He is also a researcher and a longtime member of the C++ community. His research interests include programming tools for dependable software. Prior to joining Microsoft, he was Assistant Professor at Texas A&M University. Dr. Dos Reis was a recipient of the 2012 National Science Foundation CAREER award for his research in compilers for dependable computational mathematics and educational activities. He is a member of the C++ standardization committee.

    References

    1. Wikipedia. Undefined Behavior.
    2. A Guide to Undefined Behavior in C and C++. Part 1, 2, 3.
    3. Wikipedia. offsetof.
    4. LLVM Blog. What Every C Programmer Should Know About Undefined Behavior #2/3.
    5. LWN. Fun with NULL pointers. Part 1, 2.

    Imagen del icono: 

    Image may be NSFW.
    Clik here to view.
  • Académico
  • Educación
  • Desarrollo de juegos
  • Código abierto
  • Seguridad
  • C/C++
  • Code for Good
  • Desarrollo de juegos
  • Windows*
  • Sistemas integrados
  • Escritorio
  • Desarrolladores
  • Profesores
  • Estudiantes
  • Apple iOS*
  • Apple OS X*
  • Arduino
  • Linux*
  • Microsoft Windows* (XP, Vista, 7)
  • Microsoft Windows* 10
  • Microsoft Windows* 8.x
  • Unix*
  • Incluir en RSS: 

    1
  • Avanzado
  • Principiante
  • Intermedio
  • The Last Line Effect

    Image may be NSFW.
    Clik here to view.
    Copy-Paste

    I have studied numbers of errors caused by using the Copy-Paste method and can assure you that programmers most often tend to make mistakes in the last fragment of a homogeneous code block. I have never seen this phenomenon described in books on programming, so I decided to write about it myself. I called it the "last line effect".

    Introduction

    My name is Andrey Karpov and I do an unusual job - I analyze program code of various applications with the help of static analyzers and write descriptions of errors and defects I find. I do this for pragmatic and mercenary reasons because what I do is the way our company advertises its tools PVS-Studio and CppCat. The scheme is very simple. I find bugs. Then I describe them in an article. The article attracts our potential customers' attention. Profit. But today's article is not about the analyzers.

    When carrying out analysis of various projects, I save bugs I find and the corresponding code fragments in a special database. By the way, anyone interested can take a look at this database. We convert it into a collection of html-pages and upload them to our website in the "Detected errors" section.

    This database is unique indeed! It currently contains 1800 code fragments with errors and is waiting for programmers to study it and reveal certain regularity patterns among these errors. That may serve as a useful basis for many future researches, manuals and articles.

    I have never carried out any special investigation of the material gathered by now. One pattern, however, is showing up so clearly that I decided to investigate it a bit deeper. You see, in my articles I have to write the phrase "note the last line" pretty often. It occurred to me that there had to be some reason behind it.

    Last line effect

    When writing program code, programmers often have to write a series of similar constructs. Typing the same code several times is boring and inefficient. That's why they use the Copy-Paste method: a code fragment is copied and pasted several times with further editing. Everyone knows what is bad about this method: you risk easily forgetting to change something in the pasted lines and thus giving birth to errors. Unfortunately, there is often no better alternative to be found.

    Now let's speak of the pattern I discovered. I figured out that mistakes are most often made in the last pasted block of code.

    Here is a simple and short example:

    inline Vector3int32& operator+=(const Vector3int32& other) {
      x += other.x;
      y += other.y;
      z += other.y;
      return *this;
    }

    Note the line "z += other.y;". The programmer forgot to replace 'y' with 'z' in it.

    You may think this is an artificial sample, but it is actually taken from a real application. Further in this article, I am going to convince you that this is a very frequent and common issue. This is what the "last line effect" looks like. Programmers most often make mistakes at the very end of a sequence of similar edits.

    I heard somewhere that mountain-climbers often fall off at the last few dozens of meters of ascent. Not because they are tired; they are simply too joyful about almost reaching the top - they anticipate the sweet taste of victory, get less attentive, and make some fatal mistake. I guess something similar happens to programmers.

    Now a few figures.

    Having studied the bug database, I singled out 84 code fragments that I found to have been written through the Copy-Paste method. Out of them, 41 fragments contain mistakes somewhere in the middle of copied-and-pasted blocks. For example:

    strncmp(argv[argidx], "CAT=", 4) &&
    strncmp(argv[argidx], "DECOY=", 6) &&
    strncmp(argv[argidx], "THREADS=", 6) &&
    strncmp(argv[argidx], "MINPROB=", 8)) {

    The length of the "THREADS=" string is 8 characters, not 6.

    In other 43 cases, mistakes were found in the last copied code block.

    Well, the number 43 looks just slightly bigger than 41. But keep in mind that there may be quite a lot of homogeneous blocks, so mistakes can be found in the first, second, fifth, or even tenth block. So we get a relatively smooth distribution of mistakes throughout blocks and a sharp peak at the end.

    I accepted the number of homogeneous blocks to be 5 on the average.

    So it appears that the first 4 blocks contain 41 mistakes distributed throughout them; that makes about 10 mistakes per block.

    And 43 mistakes are left for the fifth block!

    To make it clearer, here is a rough diagram:

    Image may be NSFW.
    Clik here to view.
    A rough diagram of mistake distribution in five homogeneous code blocks.

    Figure 1. A rough diagram of mistake distribution in five homogeneous code blocks.

    So what we get is the following pattern:

    The probability of making a mistake in the last pasted block of code is 4 times higher than in any other block.

    I don't draw any grand conclusions from that. It's just an interesting observation that may be useful to know about for practical reasons - you will stay alert when writing the last fragments of code.

    Examples

    Now I only have to convince the readers that it all is not my fancy, but a real tendency. To prove my words, I will show you some examples.

    I won't cite all the examples, of course - only the simplest or most representative ones.

    Source Engine SDK

    inline void Init( float ix=0, float iy=0,
                      float iz=0, float iw = 0 )
    {
      SetX( ix );
      SetY( iy );
      SetZ( iz );
      SetZ( iw );
    }

    The SetW() function should be called at the end.

    Chromium

    if (access & FILE_WRITE_ATTRIBUTES)
      output.append(ASCIIToUTF16("\tFILE_WRITE_ATTRIBUTES\n"));
    if (access & FILE_WRITE_DATA)
      output.append(ASCIIToUTF16("\tFILE_WRITE_DATA\n"));
    if (access & FILE_WRITE_EA)
      output.append(ASCIIToUTF16("\tFILE_WRITE_EA\n"));
    if (access & FILE_WRITE_EA)
      output.append(ASCIIToUTF16("\tFILE_WRITE_EA\n"));
    break;

    The last block and the one before it are identical.

    ReactOS

    if (*ScanString == L'\"' ||
        *ScanString == L'^' ||
        *ScanString == L'\"')

    Multi Theft Auto

    class CWaterPolySAInterface
    {
    public:
        WORD m_wVertexIDs[3];
    };
    CWaterPoly* CWaterManagerSA::CreateQuad (....)
    {
      ....
      pInterface->m_wVertexIDs [ 0 ] = pV1->GetID ();
      pInterface->m_wVertexIDs [ 1 ] = pV2->GetID ();
      pInterface->m_wVertexIDs [ 2 ] = pV3->GetID ();
      pInterface->m_wVertexIDs [ 3 ] = pV4->GetID ();
      ....
    }

    The last line was pasted mechanically and is redundant. There are only 3 items in the array.

    Source Engine SDK

    intens.x=OrSIMD(AndSIMD(BackgroundColor.x,no_hit_mask),
                    AndNotSIMD(no_hit_mask,intens.x));
    intens.y=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
                    AndNotSIMD(no_hit_mask,intens.y));
    intens.z=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
                    AndNotSIMD(no_hit_mask,intens.z));

    The programmer forgot to replace "BackgroundColor.y" with "BackgroundColor.z" in the last block.

    Trans-Proteomic Pipeline

    void setPepMaxProb(....)
    {
      ....
      double max4 = 0.0;
      double max5 = 0.0;
      double max6 = 0.0;
      double max7 = 0.0;
      ....
      if ( pep3 ) { ... if ( use_joint_probs && prob > max3 ) ... }
      ....
      if ( pep4 ) { ... if ( use_joint_probs && prob > max4 ) ... }
      ....
      if ( pep5 ) { ... if ( use_joint_probs && prob > max5 ) ... }
      ....
      if ( pep6 ) { ... if ( use_joint_probs && prob > max6 ) ... }
      ....
      if ( pep7 ) { ... if ( use_joint_probs && prob > max6 ) ... }
      ....
    }

    The programmer forgot to replace "prob > max6" with "prob > max7" in the last condition.

    SeqAn

    inline typename Value<Pipe>::Type const & operator*() {
      tmp.i1 = *in.in1;
      tmp.i2 = *in.in2;
      tmp.i3 = *in.in2;
      return tmp;
    }

    SlimDX

    for( int i = 0; i < 2; i++ )
    {
      sliders[i] = joystate.rglSlider[i];
      asliders[i] = joystate.rglASlider[i];
      vsliders[i] = joystate.rglVSlider[i];
      fsliders[i] = joystate.rglVSlider[i];
    }

    The rglFSlider array should have been used in the last line.

    Qt

    if (repetition == QStringLiteral("repeat") ||
        repetition.isEmpty()) {
      pattern->patternRepeatX = true;
      pattern->patternRepeatY = true;
    } else if (repetition == QStringLiteral("repeat-x")) {
      pattern->patternRepeatX = true;
    } else if (repetition == QStringLiteral("repeat-y")) {
      pattern->patternRepeatY = true;
    } else if (repetition == QStringLiteral("no-repeat")) {
      pattern->patternRepeatY = false;
      pattern->patternRepeatY = false;
    } else {
      //TODO: exception: SYNTAX_ERR
    }

    'patternRepeatX' is missing in the very last block. The correct code looks as follows:

    pattern->patternRepeatX = false;
    pattern->patternRepeatY = false;

    ReactOS

    const int istride = sizeof(tmp[0]) / sizeof(tmp[0][0][0]);
    const int jstride = sizeof(tmp[0][0]) / sizeof(tmp[0][0][0]);
    const int mistride = sizeof(mag[0]) / sizeof(mag[0][0]);
    const int mjstride = sizeof(mag[0][0]) / sizeof(mag[0][0]);

    The 'mjstride' variable will always be equal to one. The last line should have been written like this:

    const int mjstride = sizeof(mag[0][0]) / sizeof(mag[0][0][0]);

    Mozilla Firefox

    if (protocol.EqualsIgnoreCase("http") ||
        protocol.EqualsIgnoreCase("https") ||
        protocol.EqualsIgnoreCase("news") ||
        protocol.EqualsIgnoreCase("ftp") ||          <<<---
        protocol.EqualsIgnoreCase("file") ||
        protocol.EqualsIgnoreCase("javascript") ||
        protocol.EqualsIgnoreCase("ftp")) {          <<<---

    A suspicious string "ftp" at the end - it has already been compared to.

    Quake-III-Arena

    if (fabs(dir[0]) > test->radius ||
        fabs(dir[1]) > test->radius ||
        fabs(dir[1]) > test->radius)

    The value from the dir[2] cell is left unchecked.

    Clang

    return (ContainerBegLine <= ContaineeBegLine &&
            ContainerEndLine >= ContaineeEndLine &&
            (ContainerBegLine != ContaineeBegLine ||
             SM.getExpansionColumnNumber(ContainerRBeg) <=
             SM.getExpansionColumnNumber(ContaineeRBeg)) &&
            (ContainerEndLine != ContaineeEndLine ||
             SM.getExpansionColumnNumber(ContainerREnd) >=
             SM.getExpansionColumnNumber(ContainerREnd)));

    At the very end of the block, the "SM.getExpansionColumnNumber(ContainerREnd)" expression is compared to itself.

    MongoDB

    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;
    }

    The programmer forgot about "r." in the last line.

    Unreal Engine 4

    static bool PositionIsInside(....)
    {
      return
        Position.X >= Control.Center.X - BoxSize.X * 0.5f &&
        Position.X <= Control.Center.X + BoxSize.X * 0.5f &&
        Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f &&
        Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f;
    }

    The programmer forgot to make 2 edits in the last line. Firstly, ">=" should be replaced with "<=; secondly, minus should be replaced with plus.

    Qt

    qreal x = ctx->callData->args[0].toNumber();
    qreal y = ctx->callData->args[1].toNumber();
    qreal w = ctx->callData->args[2].toNumber();
    qreal h = ctx->callData->args[3].toNumber();
    if (!qIsFinite(x) || !qIsFinite(y) ||
        !qIsFinite(w) || !qIsFinite(w))

    In the very last call of the function qIsFinite, the 'h' variable should have been used as an argument.

    OpenSSL

    if (!strncmp(vstart, "ASCII", 5))
      arg->format = ASN1_GEN_FORMAT_ASCII;
    else if (!strncmp(vstart, "UTF8", 4))
      arg->format = ASN1_GEN_FORMAT_UTF8;
    else if (!strncmp(vstart, "HEX", 3))
      arg->format = ASN1_GEN_FORMAT_HEX;
    else if (!strncmp(vstart, "BITLIST", 3))
      arg->format = ASN1_GEN_FORMAT_BITLIST;

    The length of the "BITLIST" string is 7, not 3 characters.

    Let's stop here. I hope the examples I have demonstrated are more than enough.

    Conclusion

    From this article you have learned that with the Copy-Paste method making a mistake in the last pasted block of code is 4 times more probable than in any other fragment.

    It has to do with the specifics of human psychology, not professional skills. I have shown you in this article that even highly-skilled developers of such projects as Clang or Qt tend to make mistakes of this kind.

    I hope my observation will be useful for programmers and perhaps urge them to investigate our bug database. I believe it will help reveal many regularity patterns among errors and work out new recommendations for programmers.

  • C++ sample
  • code review
  • Code
  • C/C++
  • copy-paste
  • Imagen del icono: 

    Image may be NSFW.
    Clik here to view.
  • Artículo técnico
  • Académico
  • Herramientas de desarrollo
  • Educación
  • Desarrollo de juegos
  • Código abierto
  • Seguridad
  • C/C++
  • Code for Good
  • Desarrollo de juegos
  • UX
  • Windows*
  • Sistemas integrados
  • Portátil
  • Escritorio
  • Desarrolladores
  • Profesores
  • Estudiantes
  • Android*
  • Apple iOS*
  • Apple OS X*
  • Arduino
  • Google Chrome OS*
  • Linux*
  • MeeGo*
  • Microsoft Windows* (XP, Vista, 7)
  • Microsoft Windows* 10
  • Microsoft Windows* 8.x
  • Moblin*
  • Tizen*
  • Unix*
  • Proyecto Yocto
  • Incluir en RSS: 

    1
  • Principiante
  • Intermedio
  • Explicit offload for Quantum ESPRESSO

    Purpose

    This code recipe describes how to get, build, and use the Quantum ESPRESSO code that includes support for the Intel® Xeon Phi™ coprocessor with Intel® Many-Integrated Core (MIC) architecture. This recipe focuses on how to run this code using explicit offload.

    Code Access

    Quantum ESPRESSO is an integrated suite of open source computer codes for electronic-structure calculations and materials modeling at the nanoscale. It is based on density-functional theory, plane waves, and pseudo potentials. The Quantum ESPRESSO code is maintained by Quantum ESPRESSO Foundation and is available under the GPLv2 licensing agreement. The code supports the offload mode of operation of the Intel® Xeon® processor (referred to as ‘host’ in this document) with the Intel® Xeon Phi™ coprocessor (referred to as ‘coprocessor’ in this document) in a single node and in a cluster environment.

    To get access to the code and test workloads:

    1. Download the latest Quantum ESPRESSO version from http://www.quantum-espresso.org/download/
    2. Clone the linear algebra package libxphi from Gibthub:

      $ git clone https://github.com/cdahnken/libxphi.

    Build Directions

    1. Untar the Quantum ESPRESSO tarball
      $ tar xzf espresso-5.1.tar.gz
    2. Source the Intel® compiler and Intel® MPI Library

      $ source /opt/intel/composer_xe_2013_sp1.4.211/bin/compilervars.sh intel64
      $ source /opt/intel/impi/latest/bin64/mpivars.sh
    3. Change to the espresso directory and run the configure script
      $ cd espresso-5.1
      $ export SCALAPACK_LIBS="-lmkl_scalapack_lp64 -lmkl_blacs_intelmpi_lp64"
      $ export LAPACK_LIBS="-mkl=parallel"
      $ export BLAS_LIBS="-mkl=parallel"
      $ export FFT_LIBS="-mkl=parallel"
      $ export MPIF90=mpiifort
      $ export AR=xiar
      $ ./configure --enable-openmp
    4. Make sure make.sys (by editing make.sys) has the following configuration:
      MANUAL_DFLAGS = -D__KNC_OFFLOAD
      FLAGS =  -D__INTEL -D__FFTW -D__MPI -D__PARA -D__SCALAPACK  -D__OPENMP $(MANUAL_DFLAGS)
      MOD_FLAG = -I<PATH_TO_PW> -I
      MPIF90 = mpif90
      CC = icc
      F77 = ifort
      BLAS_LIBS =  "-mkl=parallel"
      BLAS_LIBS_SWITCH = external
      LAPACK_LIBS = "-mkl=parallel"
      LAPACK_LIBS_SWITCH = external
      SCALAPACK_LIBS = -lmkl_scalapack_lp64 -lmkl_blacs_intelmpi_lp64
      FFT_LIBS =  "-mkl=parallel"

      You can add “-xHost -ansi-alias” to CFLAGS as well as FFLAGS.

    5. Build the Quantum ESPRESSO PW binary
      $ make pw -j16

      You should now have bin/pw.x

    6. Change to the directory you cloned libxphi to and execute the build script. Make sure you do this in the shell you have the Intel compilers and Intel MPI library sourced.
      $ cd libxphi
      $ ./build-library.sh

      You should now find two libraries: libxphi.so and libmkl_proxy.so

    The build process is now complete.

    Run Directions

    A single Quantum ESPRESSO on a single node

    The Quantum ESPRESSO binary compiled above initially has support for accelerated 3D FFT. Additionally, the library libxphi.so contains a number of linear algebra numerical routines invoked by Quantum ESPRESSO, particularly the numerically intensive ZGEMM BLAS3 routine for complex matrix-matrix multiplication. Instead of executing this routine via Intel® Math Kernel Library (Intel MKL), libxphi blocks the matrices and buffers them asynchronously to the card, where Intel MKL then executes the multiplication of the blocks and transfers the result back. When the Quantum ESPRESSO binary is created with the build instructions above, it will contain dynamic calls to the ZGEMM routine, which are usually satisfied by Intel MKL. To get offloaded ZGEMM in place, libxphi.so needs to be preloaded:

    $ export LD_LIBRARY_PATH=$PATH_TO_LIBXPH:$LD_LIBRARY_PATH
    $ LD_PRELOAD=”$PATH_TO_LIBXPHI/libxphi.so” ./pw.x <pw arguments>

    The last line executes the Quantum ESPRESSO binary pw.x with offloaded ZGEMM support. To make this easier, we provide a shell script that facilitates this preloading and just takes the binary and its arguments as input, so that the execution of an offloaded run would look like this:

    $ <PATH_TO_LIBPXPHI>/xphilibwrapper.sh <PATH_TO_PW>/pw.x <pw arguments>.

    In this case Quantum ESPRESSO will execute a single instance with OpenMP* threads (by default as many as you have cores) and offload FFT and ZGEMM to all the cores of the Intel Xeon Phi coprocessor.

    Tuning the linear algebra offloading

    To tune the offloading process, we need to understand the ZGEMM routine, which executes matrix-matrix multiplication

    C=αA∙B+βC

    where α and β are complex numbers and C, A and B are matrices of dimension MxN, MxK, and KxN, respectively. The library libxphi.so now blocks this matrix-matrix multiplication, so that the resulting block-matrix multiplication consists of smaller blocks that are continuously streamed to the coprocessor and back. The size of those blocks can be defined by three parameters, M, N, and K, where m x n, m x k, and k x n are the dimensions of the C-, A- and B-block, respectively. By default, libxphi will block the matrices in sizes of m=n=k =1024.You can play with these values to achieve better performance, depending on your workload size. We have found that making m and n somewhat larger (m=n=2048) and playing with the size of k (between 512 and 1024) can yield very good results.

    Block size can be set via the environment variables QE_MIC_BLOCKSIZE_M, QE_MIC_BLOCKSIZE_N, and QE_MIC_BLOCKSIZE_K. For example:

    $ QE_MIC_BLOCKSIZE_M=2048
    $ QE_MIC_BLOCKSIZE_N=2048
    $ QE_MIC_BLOCKSIZE_K=512

    An additional setting is required to avoid the offloading of small matrices, which might be more efficiently computed on the host instead of the coprocessor. With QE_MIC_OFFLOAD_THRESHOLD you can define the minimal number of floating point operations a matrix must have in order to get offloaded. The setting

    $  export QE_MIC_OFFLOAD_THRESHOLD=20

    achieves good results.

    Partitioning the coprocessor

    Partitioning the coprocessor leverages the advantages of multi-processing vs. multi-threading. It is somewhat similar to running Message Passing Interface (MPI) ranks on the coprocessor (a.k.a. symmetric usage model) although the MPI ranks are only on the host. Varying the number of ranks on the host can be used to partition each coprocessor into independent sets of threads. The vehicle to achieve independent thread-partitions is given by the KMP_PLACE_THREADS environment variable. In addition, using the environment variable OFFLOAD_DEVICES utilizes multiple coprocessors within the same system. Of course there is nothing wrong with using OpenMP instead of this proposed method; however, we found that portioning the coprocessor unlocks more performance–this is simply trading implicit locks at the end of parallel regions against absolutely independent executions. To ease the tuning process, a script is provided that generates the appropriate “mpirun”-command line.

    $ ~/mpirun/mpirun.sh -h
        -n: list of comma separated node names
        -p: number of processes per socket (host)
        -q: number of processes per mic (native)
        -s: number of sockets per node
        -d: number of devices per node
        -e: number of CPU cores per socket
        -t: number of CPU threads per core
        -m: number of MIC cores per device
        -r: number of MIC cores reserved
        -u: number of MIC threads per core
        -a: affinity (CPU) e.g., compact
        -b: affinity (MIC) e.g., balanced
        -c: schedule, e.g., dynamic
        -0: executable (rank-0)
        -x: executable (host)
        -y: executable (mic)
        -z: prefixed mic name
        -i: inputfile (<)
        -w: wrapper
        -v: dryrun

    The script “mpirun.sh” is actually inspecting the system hardware in order to provide defaults for all of the above arguments. The script then launches “mpirun.py,” which actually builds and launches the command line for “mpirun.” This initial inspection, for example, avoids using multiple host sockets in case there is only one coprocessor attached to the system (avoids performing data transfers to a “remote” coprocessor). Any default provided by the launcher script “mpirun.sh” can be overridden at the command line (while still being able to leverage all other default settings). Please note that the script also supports symmetric execution (“-y”, etc.), which is discussed here.

    Here is an example of running QE with four partitions on each of the coprocessor(s):

    $ ./mpirun.sh -p4
        -w <PATH_TO_LIBPXPHI>/xphilibwrapper.sh
        -x <PATH_TO_PW>/pw.x
        -i <input-file.in>

    Any argument passed at the end of the command line is simply forwarded to the next underlying mechanism if not consumed by option processing. If you need to pass arguments to the executable using “<”, you can use the script’s “-i” option; otherwise, options for the executable can be simply appended to the above command line.

    The number of ranks per host-socket (“-p”) is not only dividing the number of cores per host-processor but also dividing each coprocessor’s number of cores. Therefore some ratios produce some remaining unused cores. On the other hand, the coprocessor usually comes with more cores than cores in a single host socket/processor; therefore, it is likely acceptable and anyways a subject of tuning the number of partitions.

    Performance

    Image may be NSFW.
    Clik here to view.
    Performance of Quantum Espresso 5.0.3 GRIR443

    Figure 1: Performance of Quantum Espresso executing the GRIR443 benchmark on 16 Xeon E5-2697v2 and 16 Xeon Phi 7120A.
    Software and workloads used in performance tests may have been optimized for performance only on Intel microprocessors. Performance tests, such as SYSmark* and MobileMark*, are measured using specific computer systems, components, software, operations, and functions. Any change to any of those factors may cause the results to vary. You should consult other information and performance tests to assist you in fully evaluating your contemplated purchases, including the performance of that product when combined with other products.

    Application parameterization

    • -npool=2,
    • 2 MPI ranks/socket
    • 6 threads/MPI rank

    Platform configuration

    Host configuration

    • Intel® Xeon® processor E5-2697 v2 64GB
    • 64GB DDR3-1600
    • RHEL 6.4
    • Intel® Turbo Boost Technology /EIST/SMT/NUMA enabled

    MIC configuration

    • 7120A, 61cores, 1.238GHz
    • MPSS 2.1.6720-16
    • ECC enabled, Turbo disabled

    Software configuration

    • Icc 14.0.0 update 1, Intel MPI Library 14.1.1.036 
  • Quantum ESPRESSO
  • Intel® Xeon Phi™ Coprocessor
  • Desarrolladores
  • Linux*
  • Servidor
  • Intermedio
  • Intel® MPI Library
  • Arquitectura Intel® para muchos núcleos integrados
  • Dirección URL

  • Let's Play a Game - find bugs in popular open-source projects

    Authors of PVS-Studio static code analyzers offer programmers to test their sight and to try finding errors in C/C++ code fragments.

    Code analyzers work tirelessly and are able to find many bugs that can be difficult to notice. We chose some code fragments in which we had founded some errors using PVS-Studio.

    Quiz is not intended to check C++ language knowledge. There are many quality and interesting tests. For instance, we would recommend this C++ Quiz then. In our case, we made our test just for fun.

    We quite frequently hear an opinion that code analyzers are pointless tools. It is possible to find misplaced parenthesis or comma in five seconds. However, analyzer would not find difficult logical errors. Therefore, this tool could be useful only for students.

    We decided to troll these people. There is a time limit in tests. We ask them to find an error in five seconds. Well, OK, not in five seconds, but in a minute. Fifteen randomly selected problems would be shown. Every solved problem worth one point, but only if user provided the answer in one minute.

    We want to stress that we are not talking about syntax errors. We found all these code fragments in open-source projects that compiles flawlessly. Let us explain on a pair of examples how to point out the correct answer.

    First example. For instance, you got this code:

    Image may be NSFW.
    Clik here to view.
    Example N1

    The bug here is highlighted with red color. Of course, there would be no such emphasizing in a quiz problem.

    Programmer accidently made a misprint and wrote index 3 instead of index 2. Mouse cursor movement would highlight fragments of code, such as words and numbers. You should point the cursor into number 3 and press left mouse button.

    This would be the correct answer.

    Second example. It is not always possible to point out the error exactly.

    Image may be NSFW.
    Clik here to view.
    Example N2

    Buffer size should be compared with number 48. An excess sizeof operator was put there by accident. In result, buffer size is compared with size of int type.

    At my opinion, an error there is in sizeof operator, and it is required to point it out to score a correct answer. However, without knowledge about the whole text, it is possible to think this way. Sizeof operator should have evaluated the size of some buffer, but accidently evaluates the value of the macro. The error is in SSL3_MASTER_SECRET_LENGTH usage.

    In this case, the answer will be scored no matter what you choose: sizeof or SSL3_MASTER_SECRET_LENGTH.

    Good luck! You can start a game.

    Footnote.

    Test does not support mobile devices. It is very easy to miss with finger. We are working on new version of tests with better mobile devices support, new problems to solve etc. However, it is not implemented yet.

    Imagen del icono: 

    Image may be NSFW.
    Clik here to view.
  • Ejemplos de código
  • Mensajes de error y de diagnóstico
  • Artículo técnico
  • Académico
  • Herramientas de desarrollo
  • Educación
  • Código abierto
  • Seguridad
  • Experiencia del usuario y diseño
  • C/C++
  • Code for Good
  • Desarrollo de juegos
  • UX
  • Windows*
  • Escritorio
  • Desarrolladores
  • Profesores
  • Estudiantes
  • Linux*
  • Microsoft Windows* (XP, Vista, 7)
  • Microsoft Windows* 10
  • Microsoft Windows* 8.x
  • Unix*
  • Incluir en RSS: 

    1
  • Principiante
  • Intermedio
  • Intel® System Studio - Solutions, Tips and Tricks

  • Desarrolladores
  • Android*
  • Tizen*
  • Unix*
  • Yocto Project
  • Android*
  • Tizen*
  • C/C++
  • Avanzado
  • Principiante
  • Intermedio
  • Intel® System Studio
  • Intel® Advanced Vector Extensions
  • Intel® Streaming SIMD Extensions
  • Teléfono
  • Equipo Tableta
  • Dirección URL
  • Ejemplo de código
  • Temas de compilador
  • Comprobación de errores
  • Empecemos
  • Mejora del rendimiento
  • Bibliotecas
  • Errores de memoria
  • Desarrollo de Multi-subprocesos
  • Análisis de seguridad estática
  • Errores de subprocesamiento
  • ISS-Learn
  • Learning Lab
  • Internet of Things: A Plant Monitor on the Intel® Edison Board

    Introduction

    Over the past several years, the Internet of Things (IOT) has gained increasing attention from developers and consumers alike. You can now control almost everything in your home from your AC to your lights with a simple click of an app on your phone. In this article we make a plant monitor using the Intel® Edison board that autonomously waters a plant when the moisture level is too low and gives you the option to water on your command. Now you never have to worry about forgetting to water your plants, and your plants will be watered even when you’re out of town. You can follow this project on Twitter*: Intel Edison @PlantMonitor. We use the Arduino* IDE to write our sketch program to control the Intel Edison board. The data and other variables are sent to ThingSpeak* for data visualizations and tweeting. Links to all the necessary external libraries can be found at the end of this article. For more information on the Intel Edison board and Arduino IDE downloads: https://www-ssl.intel.com/content/www/us/en/do-it-yourself/edison.html.

    Contents:

    1. Moisture Sensor
    2. Light Sensor
    3. LED Pixel Matrix
    4. Peristaltic Pump
    5. ThingSpeak
    6. Sketch Setup()
    7. Sketch Loop()

    Image may be NSFW.
    Clik here to view.

    Figure 1: Plant Monitor

    1.Moisture Sensor

    The main component of our plant monitor is the moisture sensor; we use the Sunkee* soil hygrometer detection module. It measures the resistance between the two prongs in the soil to determine moisture content. We record the max and min of the sensor in the setup() to map the plant value to a percentage in the main loop(); below they are currently set to initial dummy values. The max value is the reading of air when the resistance is the greatest and the min value is when the sensor is completely submerged in water when resistance is the least. The value comes over as an analog input and we power it when needed using one of the digital pins to reduce the effects of electrolysis.  We also set a percentage threshold for the plant to determine if it is overwatered, under-watered, or just right, and from those values trigger watering the plant when needed.  

    // Analog pin which we're monitoring
    
    const int soilSensorPin = A0;
    
    const int soilSensorPower = 7;
    
    // soil variables:
    
    int soil=0;
    
    int soilSensorValue = 0;         // the sensor value
    
    int soilSensorMin = 1000;         // min/wet sensor value
    
    int soilSensorMax = 0;         // max/dry sensor value
    
    int overWaterThreshold=75;
    
    int underWaterThreshold=50;

    Code Example 1: Globals for the moiture sensor**

    2.Light Sensor

    As an added feature we also record the light level of the plant. Maybe the sunny spot it’s in only lasts a few hours but it needs sun all day long, so you know to move it to another spot. The Adafruit* TSL2561 high dynamic range digital light sensor is a sophisticated sensor that provides a much more accurate read than a photocell. It uses an I2C clock and an I2C data pin to communicate with the board. It requires two external libraries, the Adafruit Sensor library and the Adafruit TSL2561 library. You can learn more about it here: https://learn.adafruit.com/tsl2561/use

    //for light and 8x8 bicolor LED
    #include <Wire.h>
    //for light sensor
    #include <Adafruit_Sensor.h>
    #include <Adafruit_TSL2561_U.h>
    Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
    void configureSensor(void){
      tsl.enableAutoGain(true);          /* Auto-gain ... switches automatically between 1x and 16x */
    
      /* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
      tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);      /* fast but low resolution */
    }

    Code Example 2: Globals for the light sensor**

    3.LED Pixel Matrix

    As a visual indicator of the plant status, we added an 8x8 Adafruit BiColor LED square pixel matrix with an I2C backpack to the plant monitor. It requires the same I2C pins as the light sensor, which is fine as I2C can communicate with multiple devices on the same bus. We can easily print words to the matrix, but to print our own shapes, we must define a binary 8x8 matrix so it knows which LEDs to turn on and off. When we write the shape to the matrix we also choose the color to indicate the status being bad or good. Below we defined a custom shape for the number ten as the default text version looks oddly small compared to numbers one through nine, a Wi-Fi signal to indicate the board cannot connect to ThingSpeak, a leaf for the plant status, and a question mark for when the data cannot be parsed from ThingSpeak. You can find more information about the LED matrix and the two external required libraries: https://learn.adafruit.com/adafruit-led-backpack/bi-color-8x8-matrix

    //for light and 8x8 bicolor LED
    #include <Wire.h>
    //for 8x8 bicolor LED
    #include "Adafruit_LEDBackpack.h"
    #include "Adafruit_GFX.h"
    Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
    static const uint8_t PROGMEM
    ten_bmp[] =
    {
      B01001111,
      B11001001,
      B01001001,
      B01001001,
      B01001001,
      B01001001,
      B11101111,
      B00000000 }
    ,
    wifi_bmp[] =
    {
      B11100001,
      B01000001,
      B01000101,
      B01000101,
      B01010101,
      B01010101,
      B01010101,
      B00000000 }
    ,
    leaf_bmp[] =
    {
      B00010000,
      B00101000,
      B01000100,
      B01001010,
      B01001010,
      B00101010,
      B00011100,
      B00001000 }
    ,
    question_bmp[] =
    {
      B00111000,
      B01000100,
      B01000100,
      B00001000,
      B00010000,
      B00010000,
      B00000000,
      B00010000 }
    ;

    Code Example 3: Globals for the LED Matrix**

    4.Peristaltic Pump

    Also from Adafruit, a 12V peristaltic liquid pump with silicone tubing is used to water the plant when the moisture level gets too low. The advantage of a peristaltic pump is that it won’t be damaged if there is no more liquid to draw from the reservoir. Adding an eTape* Liquid Level Sensor to the water reservoir itself to alert the user if that water level is low would be a good addition to this project. The pump requires its own separate 12V power supply, and as the board can only put out a max of 5V, the power supply is controlled by a relay switch that is in turn controlled by a pin on the board.

    // Pin to drive the relay attached to the pump; high is off, low is on
    int pump=2;

    Code Example 4: Globals for the pump**

    Image may be NSFW.
    Clik here to view.

    Figure 2: Diagram of the plant monitor

    5.ThingSpeak

    It wouldn’t be an IOT device without the Internet! So we will use a website that supports real time data collection and visualizations. For this project we use ThingSpeak which is currently offering its services for free and also tweets your project’s status (https://thingspeak.com/ ), but many other providers are available to choose from as well.

    Below are the global variables that ThingSpeak needs, the most important being the thingSpeakChannel number and the writeAPIKey that will allow you to post to your feed. We also use the ArduinoJson Parser library to parse the ThingSpeak reads. 

    //for ThingSpeak
    #include <WiFi.h>
    #include <JsonParser.h>
    // ThingSpeak Settings
    WiFiClient clientWifi;
    char thingSpeakAddress[] = "api.thingspeak.com";
    String thingSpeakChannel = "24066";
    int TSF_moisture_sensor;
    int TSF_light_sensor;
    int TSF_raw_moisture_data;
    int TSF_raw_moisture_wettest_data; //min
    int TSF_raw_moisture_driest_data; //max
    int TSF_use_server_moisture_calibration;
    int TSF_manual_water;
    String writeAPIKey = "1KPP2Y48IZMDPISB";
    // ThingSpeak Variable Setup
    int failedCounter = 0;
    int useServerMoistureValues= 0;
    int initialSetup =0;
    String twitterTweet= "";

    Code Example 5: Globals for ThingSpeak**

    Below is the method to read from your specified ThingSpeak feed. To fetch the data from your channel make sure that “Make Public?” is checked in your Channel Settings on the ThingSpeak website. If we have any issues connecting to the service, we change the LED to a red Wi-Fi signal for the user to see. 

    void subscribeToThingSpeak(String tsChannel){
      if (clientWifi.connect(thingSpeakAddress, 80)){
        failedCounter = 0;
        clientWifi.println("GET /channels/"+tsChannel+"/feeds/last");
        clientWifi.println();
      }
      else{
        failedCounter++;
        Serial.println("Read Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");
        Serial.println();
        matrix.clear();
        matrix.drawBitmap(0, 0, wifi_bmp, 8, 8, LED_RED);
        matrix.writeDisplay();
      }
    }

    Code Example 6: Update method for ThingSpeak **

    To update ThingSpeak, we send our string of data for it to parse and add to our graphs as well as our tweet. The composition of the data string will be discussed later on. To update Twitter make sure that the desired Twitter account is linked into ThingTweet in the apps section of ThingSpeak. If there are any issues connecting, we again set the LED matrix to the red Wi-Fi signal. 

    void updateThingSpeak(String tsData)
    {
      if (clientWifi.connect(thingSpeakAddress, 80)){
        clientWifi.print("POST /update HTTP/1.1\n");
        clientWifi.print("Host: api.thingspeak.com\n");
        clientWifi.print("Connection: close\n");
        clientWifi.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
        clientWifi.print("Content-Type: application/x-www-form-urlencoded\n");
        clientWifi.print("Content-Length: ");
        clientWifi.print(tsData.length());
        clientWifi.print("\n\n");
        clientWifi.print(tsData);
    
        if (clientWifi.connected()){
          Serial.println("Updated ThingSpeak");
          Serial.println();
          failedCounter = 0;
        }
        else{
          failedCounter++;
          Serial.println("Update connection to ThingSpeak failed ("+String(failedCounter, DEC)+")");
          matrix.clear();
          matrix.drawBitmap(0, 0, wifi_bmp, 8, 8, LED_RED);
          matrix.writeDisplay();
          Serial.println();
        }
    
      }
      else{
        failedCounter++;
        Serial.println("Updating ThingSpeak Failed ("+String(failedCounter, DEC)+")");
        Serial.println();
        matrix.clear();
        matrix.drawBitmap(0, 0, wifi_bmp, 8, 8, LED_RED);
        matrix.writeDisplay();
      }
    }

    Code Example 7: Read method for ThingSpeak**

    ThingSpeak then graphs each field of your data in a separate chart. In the image below you can see the moisture percentage slowly decreasing and the raw moisture data slowly increasing as resistance increases between the probes. We can also see that the light in the room came on at around 6:30am that day. 

    Image may be NSFW.
    Clik here to view.

    Figure 3: Screenshot of ThingSpeak

    6.Sketch Setup()

    The first main part of the Arduino sketch is the setup loop that runs once on start up. It is here that we setup everything we need for our moisture sensor. First is the setup of the pump pin and then turning it off in the code to make sure the pump is not pumping water. 

    void setup() {
       Serial.begin(9600);
       pinMode(pump, OUTPUT);
      //turn the relay off
      digitalWrite(pump, HIGH);

    Code Example 8: setup() method and pump initialization**

    Then we initialize the LED matrix with the address that it is using. 

    //init the LED matrix
      matrix.begin(0x70);  // pass in the address

    Code Example 9: setup() method and LED initialization**

    Next we set up the calibration of our plant monitor. The raw data that comes over from the moisture sensor has no meaning without a baseline high and low to compare it to. Below we show a green leaf on start-up and then print out “Calibrate Me!” and count down from ten for the user to calibrate the moisture sensor. The best way to calibrate it is to transition the sensor from being in air to submerged in a cup of water during those ten seconds and then stick it into the plant when done. If the values the user wants to use are already in ThingSpeak, then those are taken into account during the loop() part of the sketch.

    Serial.println("Starting plant monitor...");
      Serial.println();
      matrix.clear();
      matrix.drawBitmap(0, 0, leaf_bmp, 8, 8, LED_GREEN);
      matrix.writeDisplay();
      delay(3000);
    
      Serial.println("Soil moisture sensor");
      // add a calibration setup
      // calibrate during the first ten seconds
      Serial.println("Please calibrate your moisture sensor in the next 10 seconds");
      matrix.setTextWrap(false);  // we dont want text to wrap so it scrolls nicely
      matrix.setTextSize(1);
      matrix.setTextColor(LED_GREEN);
      for (int8_t x=7; x>=-94; x--) {
        matrix.clear();
        matrix.setCursor(x,0);
        matrix.print("Calibrate Me!");
        matrix.writeDisplay();
        delay(150);
      }
    
      int offset=1;
      for(int i=10; i>-1;i--){
        soilSensorValue = analogRead(soilSensorPin);
    
        // record the maximum sensor value
        if (soilSensorValue > soilSensorMax) {
          soilSensorMax = soilSensorValue;
        }
    
        // record the minimum sensor value
        if (soilSensorValue < soilSensorMin) {
          soilSensorMin = soilSensorValue;
        }
    
        matrix.setTextWrap(true);
        matrix.setTextSize(1);
        matrix.setTextColor(LED_GREEN);
        matrix.clear();
        if(i<10){
          matrix.setCursor(0,0);
          matrix.print(i);
        }
        else{
          switch(i){
          case 10:
            //the standard 10 looks odd, so we created our own
            matrix.drawBitmap(0, 0, ten_bmp, 8, 8, LED_GREEN);
            break;
          }
        }
        matrix.writeDisplay();
        delay(1000);
      }
      matrix.clear();

    Code Example 10: setup() method and moisture sensor calibration**

    And finally we configure our light sensor set-up and delay an additional amount of time to ensure the user has enough time to place the probe in the soil. 

    /* Initialise the light sensor */
      if(!tsl.begin())
      {
        /* There was a problem detecting the ADXL345 ... check your connections */
        Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
        while(1);
      }
      /* Setup the sensor gain and integration time */
      configureSensor();
    }
      //in case the sensor is still in the water for calibration
      delay(3000);
    }

    Code Example 11: setup() method and light sensor initialization**

    Tip

    If you encounter a sketch transfer incomplete error with a message of ‘Retry 0: Got ZCAN’, it is because your logs have filled it up with entries, leaving no more space in memory. You can either expand the memory of your board with an sdcard, or login as root over a serial connection and run ‘rm –rf /var/log/journal/*’ to delete all the logs.  

    7.Sketch Loop()

    The loop is the part of the sketch that repeats over and over, collecting data and then submitting it to ThingSpeak. It begins by reading the data from ThingSpeak using an HTTP GET call that returns a string of data in JSON format. To parse this data into local variables to see if any of the user command variables have been set, we use the ArduinoJson library to load it into a hashTable from which we can easily obtain the individual values as strings. If there is a parse failure, we assume the first failure is due to the fact that there is no data there yet and proceed forward with the sketch to upload values. If the failures persist, then we wait a while giving the issue time to clear up and then restart the loop from the beginning. 

    void loop() {
     if (clientWifi.connected()){
        clientWifi.stop();
      }
      if(!clientWifi.connected()){
        subscribeToThingSpeak(thingSpeakChannel);
      }
      String response= "";
      char charIn;
      if (clientWifi.available() > 0){
        do {
          charIn = clientWifi.read(); // read a char from the buffer
          response += charIn; // append that char to the string response
        }
        while (clientWifi.available() > 0);
    
        Serial.print("Reading ThingSpeak: ");
        Serial.println(response);
        Serial.println();
        int len= response.length()+1;
        char myString[len];
        response.toCharArray(myString,len);
        JsonParser<32> parser;
        JsonHashTable hashTable = parser.parseHashTable(myString);
        if (!hashTable.success()){
          Serial.println("JsonParser.parseHashTable() failed");
          initialSetup++;
          if(initialSetup>1){
            matrix.clear();
            matrix.drawBitmap(0, 0, question_bmp, 8, 8, LED_RED);
            matrix.writeDisplay();
            delay(30000);
            return;
          }
        }
        else{
          TSF_moisture_sensor = atoi(hashTable.getString("field1"));
          TSF_light_sensor = atoi(hashTable.getString("field2"));
          TSF_raw_moisture_data = atoi(hashTable.getString("field3"));
          TSF_raw_moisture_wettest_data = atoi(hashTable.getString("field4"));
          TSF_raw_moisture_driest_data= atoi(hashTable.getString("field5"));
          TSF_use_server_moisture_calibration = atoi(hashTable.getString("field6"));
          TSF_manual_water = atoi(hashTable.getString("field7"));

    Code Example 12: loop() method and ThingSpeak data fetching**

    If the user wants to input their own calibration values, then we check the TSF_use_server_moisture_calibration variable and set our local max and min to use the server values instead. Additionally, so the user doesn’t have to re-calibrate the sensor every time and instead keep the probe in the soil continuously, we check that the difference between the max and min is not great enough to indicate a calibration was done and proceed to use the server values. To input data into ThingSpeak outside of the sketch requires just a simple HTTP call to the ThingSpeak website using your writeAPIKey and the field numbers and values. For example, to input new calibration values and use them would be: https://api.thingspeak.com/update?key=1KPP2Y48IZMDPISB&field4=479&field5=1015&field6=1. One thing to note is that any value not included in this call will be changed to null, hence the sketch check for values that exactly equal one or are not null to prevent any errors from null data entry. 

    if((TSF_use_server_moisture_calibration==1) || ((soilSensorMax-soilSensorMin)<300)){
            if(TSF_raw_moisture_wettest_data !=NULL && TSF_raw_moisture_driest_data !=NULL){
              soilSensorMin= TSF_raw_moisture_wettest_data;
              soilSensorMax= TSF_raw_moisture_driest_data;
            }
          }
        }
      }

    Code Example 13: loop() method and moisture sensor values set-up**

    After we have our finalized max and min values we can get the soil reading by setting the pin HIGH to power the sensor before turning it off again and then mapping the value to an easily readable percentage. Based on the global threshold values, the sketch reports the status of the plant with an appropriately colored leaf on the LED matrix, compose the tweet string, and if necessary turn on the pump to water the plant. 

      digitalWrite(soilSensorPower, HIGH);
      delay(2000);
      soilSensorValue = analogRead(soilSensorPin);
      digitalWrite(soilSensorPower, LOW);
      soilSensorValue = constrain(soilSensorValue, soilSensorMin, soilSensorMax);
      //map the value to a percentage
      soil = map(soilSensorValue, soilSensorMin, soilSensorMax, 100, 0);
    
      if (soil>=overWaterThreshold){
        Serial.println("Water Level Too High");
        matrix.clear();
        matrix.drawBitmap(0, 0, leaf_bmp, 8, 8, LED_YELLOW);
        matrix.writeDisplay();
       // Update Twitter via ThingTweet
        twitterTweet="&twitter=PlantMonitor&tweet=Plant water level is too high: "+ String(soil) + "%25.";
      }
      else{
        if (soil <overWaterThreshold && soil>underWaterThreshold){
          Serial.println("Water Level Good");
          matrix.clear();
          matrix.drawBitmap(0, 0, leaf_bmp, 8, 8, LED_GREEN);
          matrix.writeDisplay();
          twitterTweet="&twitter=PlantMonitor&tweet=Plant water level is good: "+ String(soil) + "%25.";
        }
        else{
          Serial.println("Water Level Bad");
          matrix.clear();
          matrix.drawBitmap(0, 0, leaf_bmp, 8, 8, LED_RED);
          matrix.writeDisplay();
          twitterTweet="Plant water level is too low: "+ String(soil) + "%25. Watering now. ";
          digitalWrite(pump, LOW);
          delay(30000); // set how long you want the motor to run... 1000 = aprox 1ml
          digitalWrite(pump, HIGH);
        }
      }

    Code Example 14: loop() method and moisture level settings**

    If a user wants to remotely trigger watering of their plant, they can do so by setting the TSF_manual_water variable to one (https://api.thingspeak.com/update?key=1KPP2Y48IZMDPISB&field7=1). 

      if(TSF_manual_water==1){
        digitalWrite(pump, LOW);
        delay(10000); // set how long you want the motor to run... 1000 = aprox 1ml
        digitalWrite(pump, HIGH);
        TSF_manual_water=0;
      }

    Code Example 15: loop() method and manual watering**

    Next we collect the light measurement. 

      /* Get a new light sensor event */
      sensors_event_t event;
      tsl.getEvent(&event);
    
      /* Display the results (light is measured in lux) */
      if (!event.light) {
        /* If event.light = 0 lux the sensor is probably saturated
         and no reliable data could be generated! */
        Serial.println("Sensor overload");
      }

    Code Example 16: loop() method and light sensor data collection**

    And then it is time to submit all the data to ThingSpeak and tweet our plant’s status. The data string has every numbered field with its value and ends with our twitter handle and our tweet string. 

    // Disconnect from ThingSpeak
      if (clientWifi.connected()){
        clientWifi.stop();
      }
    
      // Update ThingSpeak
      if(!clientWifi.connected()){
        updateThingSpeak("field1="+String(soil) + "&field2=" + String((int)event.light)
          + "&field3=" + String(soilSensorValue) + "&field4=" + String(soilSensorMin)
          + "&field5=" + String(soilSensorMax) + "&field6=" + String(useServerMoistureValues)
          + "&field7=" + String(TSF_manual_water)+ "&twitter=PlantMonitor&tweet="+twitterTweet);
      }

    Code Example 17: loop() method and ThingSpeak data submission**

    At the very end of the loop we put a delay of one hour. The moisture level of the plant doesn’t need to be checked often, and the delay gives the water more time to disperse and settle between watering’s. 

    delay(3600000);
    }

    Code Example 18: loop() method and delay**

    Image may be NSFW.
    Clik here to view.

    Figure 4: Screenshot of Twitter

    Summary

    Now we have built our Edison plant monitor to water our plant for us. You can experiment with your own threshold levels and setting how much to water your plant. I used a small Nephthytis house plant for this project so your plants needs may be different.

     

    References and Library Links

    https://thingspeak.com/

    https://learn.adafruit.com

    https://github.com/bblanchon/ArduinoJson

    https://github.com/iobridge/ThingSpeak-Arduino-Examples

    https://github.com/adafruit/Adafruit_TSL2561

    https://github.com/adafruit/Adafruit-GFX-Library

    https://github.com/adafruit/Adafruit-LED-Backpack-Library

    https://github.com/adafruit/Adafruit_Sensor

    About the Author

    Whitney Foster is a software engineer at Intel in the Software Solutions Group working on scale enabling projects for Android applications and IOT.

    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 and the Intel logo 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 AgreementLike   SubscribeAdd new commentFlag as spam  .

    © 2015 Intel Corporation.Flag as inappropriate  Flag as Outdated 

  • Intel Edison
  • Intel Edison Board
  • IoT
  • Intel Internet of Things
  • plant monitor
  • adafruit
  • Desarrolladores
  • Profesores
  • Estudiantes
  • Arduino
  • Internet de las cosas
  • C/C++
  • Principiante
  • Intermedio
  • Internet de las cosas
  • Sensores
  • Sistemas integrados
  • Dirección URL
  • Ejemplo de código
  • Internet de las cosas
  • Fluent Conf 2015: HTML/CSS/JS and Robotics Too

    Image may be NSFW.
    Clik here to view.
    image

    Photo opp - me and the Javascript Rhino we all love!  :)

    Last week I attended Fluent Conf for the second time. It’s great to see the continuing trend of the Web + IoT and other hardware + Javascript goodness.

    Image may be NSFW.
    Clik here to view.
    image
     

    Though the main focus of this conference is on HTML/CSS/JS, quite a few of the talks this year were also focused connecting web technologies with other real world experiences. Robotics, WebVR, Wearables, etc. were all topics of presentation and there were some great talks on these subjects.

    Image may be NSFW.
    Clik here to view.
    image
     

    A lot of companies have adopted ES6 already and using Transpilers for browser compatibility. Almost everyone is giving a talk on React; it’s amazing how many companies are using it since React was announced last year. Here is Brian Holt giving a talk on using both ES6 and React together.

    Image may be NSFW.
    Clik here to view.
    image
     

    Javascript robotics! A few hardware vendor/projects were at the exhibit hall at Fluent. It’s great to see worlds collide and amazing things come out of it. Tessel is also back this year with their Tessel 2 board!

    Image may be NSFW.
    Clik here to view.
    image
     

     

    Image may be NSFW.
    Clik here to view.
    image
     

    I have been playing around with MQTT for a while and it’s great to see that now it has almost become the defacto protocol for IoT applications. I had the pleasure of attending a great talk about IoT and voice enabled applications using IBM’s BlueMix and Watson Text-To-Speech technology. The demo showed a Sphereo being controlled by voice!

    Image may be NSFW.
    Clik here to view.
    image
     

    I got to see the demo up close and had a quick chat with Stewart Nickolas, a distinguished engineer at IBM!

    Image may be NSFW.
    Clik here to view.
    image
     

    Writing apps for wearables using Javascript...what??!?! Actually, Pebble has already made that possible with their PebbleJS and PebbleKit, but it’s interesting to see that it’s actually possible on other platforms too. Dan Gallo gave a great talk on using JS on different wearable platforms.

    Image may be NSFW.
    Clik here to view.
    image
     

    I also attended a talk by Ron Evans and got this awesome Cylon.JS sticker after speaking to him in person. He put together a great talk on “Full Stack Robotics”!

    Image may be NSFW.
    Clik here to view.
    image
     

    I love my O’Reilly animal stickers :)

    I had a great time at Fluent this year (I do every year) and it’s quite interesting to see the convergence of web technologies/developers and hardware. I can’t wait to see what they have in store for next year at Fluent!

    Imagen del icono: 

    Image may be NSFW.
    Clik here to view.
  • Conferencias
  • Evento
  • HTML5
  • JavaScript*
  • HTML5
  • Internet de las cosas
  • Desarrolladores
  • Incluir en RSS: 

    1
  • Avanzado
  • Principiante
  • Intermedio
  • Intel® INDE Getting Started Guide

    Introduction

    Intel® Integrated Native Developer Experience (Intel® INDE) is a one stop productivity suite to create native applications targeting the Android* and Microsoft* Windows* platforms. This guide will help you get started with developing high performance native applications using the various features of Intel INDE. 

    Developing Windows* Applications

    Intel INDE can be used to develop Windows* applications using a Microsoft Windows* host system. For more help on using Intel INDE with this platform, refer to this guide:

    Developing Android* Applications

    Intel INDE can be used to develop Android* applications for mobile platforms using either a Microsoft Windows* host system or an Apple OS X* host system. As the tools available on each development platform are different, refer to the Getting Started Guide for your development system:

    Next Steps...

    Start developing apps with Intel INDE! See the Intel INDE Home Page for information about the different versions of the product, how to purchase it, and how to get support for the product.

     

  • Desarrolladores
  • Android*
  • Apple OS X*
  • Microsoft Windows* (XP, Vista, 7)
  • Microsoft Windows* 8.x
  • Android*
  • Windows*
  • C/C++
  • Java*
  • Principiante
  • Intermedio
  • Intel® Integrated Native Developer Experience (INDE)
  • Portátil
  • Teléfono
  • Equipo Tableta
  • Escritorio
  • Dirección URL
  • Empecemos
  • Viewing all 672 articles
    Browse latest View live


    <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>