DataLoopTest.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. 
  2. #include "../testTools.h"
  3. #define INITIALIZE \
  4. for (int i = 0; i < elements; i++) { \
  5. bufferA[i] = i % 13; \
  6. bufferB[i] = i % 7; \
  7. bufferC[i] = 0; \
  8. }
  9. #define CHECK_RESULT \
  10. { \
  11. int errors = 0; \
  12. for (int i = 0; i < elements; i++) { \
  13. if (bufferC[i] != ((i % 13) * (i % 7)) + 5) { \
  14. errors++; \
  15. } \
  16. } \
  17. ASSERT(errors == 0); \
  18. }
  19. START_TEST(DataLoop)
  20. // Allocate aligned memory
  21. const int elements = 256;
  22. int32_t allocationA[elements] ALIGN16;
  23. int32_t allocationB[elements] ALIGN16;
  24. int32_t allocationC[elements] ALIGN16;
  25. // The SafePointer class will emulate the behaviour of a raw data pointer while providing full bound checks in debug mode.
  26. SafePointer<int32_t> bufferA("bufferA", allocationA, sizeof(allocationA));
  27. SafePointer<int32_t> bufferB("bufferB", allocationB, sizeof(allocationB));
  28. SafePointer<int32_t> bufferC("bufferC", allocationC, sizeof(allocationC));
  29. // Calculate C = (A * B) + 5
  30. { // Reference implementation
  31. INITIALIZE;
  32. for (int i = 0; i < elements; i++) {
  33. bufferC[i] = (bufferA[i] * bufferB[i]) + 5;
  34. }
  35. CHECK_RESULT;
  36. }
  37. { // Pointer version
  38. INITIALIZE;
  39. // Iterating pointers are created from the main pointers
  40. SafePointer<int32_t> ptrA = bufferA;
  41. SafePointer<int32_t> ptrB = bufferB;
  42. SafePointer<int32_t> ptrC = bufferC;
  43. for (int i = 0; i < elements; i++) {
  44. // *a is the same as a[0]
  45. *ptrC = *ptrA * *ptrB + 5;
  46. // Adding one to a pointer adds the size of the element type
  47. ptrA += 1;
  48. ptrB += 1;
  49. ptrC += 1;
  50. }
  51. CHECK_RESULT;
  52. }
  53. { // Pseudo vectorization (what the SIMD math actually means)
  54. INITIALIZE;
  55. for (int i = 0; i < elements - 3; i += 4) {
  56. bufferC[i + 0] = (bufferA[i + 0] * bufferB[i + 0]) + 5;
  57. bufferC[i + 1] = (bufferA[i + 1] * bufferB[i + 1]) + 5;
  58. bufferC[i + 2] = (bufferA[i + 2] * bufferB[i + 2]) + 5;
  59. bufferC[i + 3] = (bufferA[i + 3] * bufferB[i + 3]) + 5;
  60. }
  61. CHECK_RESULT;
  62. }
  63. { // SIMD version
  64. INITIALIZE;
  65. SafePointer<int32_t> ptrA = bufferA;
  66. SafePointer<int32_t> ptrB = bufferB;
  67. SafePointer<int32_t> ptrC = bufferC;
  68. for (int i = 0; i < elements - 3; i += 4) {
  69. // Read vectors
  70. I32x4 a = I32x4::readAligned(ptrA, "data loop test @ read a");
  71. I32x4 b = I32x4::readAligned(ptrB, "data loop test @ read b");
  72. // Do the calculation with 4 elements at once from i to i + 3 using SIMD operations
  73. I32x4 result = a * b + 5;
  74. // Write the result
  75. result.writeAligned(ptrC, "data loop test @ write c");
  76. // Iterate pointers
  77. ptrA += 4;
  78. ptrB += 4;
  79. ptrC += 4;
  80. }
  81. CHECK_RESULT;
  82. }
  83. END_TEST