Below calculation is done with uboot (2009 an older version) on iMX25 processor.
I am running sha256_process() function (sha256.c) under uboot to process 50Mbytes of data to get the hash.
It takes more than 100sec to complete the calculation. While the same hashing takes no time if run with openssl under Ubuntu (same processor).
Cross Compiler:
arm-none-linux-gnueabi-gcc 4.4.1.
Need some input on what can possibly be the problem.
Tried another arm toolchain with improvement, but still not as expected.
---sha256 code.
static void sha256_process(sha256_context *ctx, const uint8_t data[64])
{
uint32_t temp1, temp2;
uint32_t W[64];
uint32_t A, B, C, D, E, F, G, H;
GET_UINT32_BE(W[0], data, 0);
GET_UINT32_BE(W[1], data, 4);
GET_UINT32_BE(W[2], data, 8);
GET_UINT32_BE(W[3], data, 12);
GET_UINT32_BE(W[4], data, 16);
GET_UINT32_BE(W[5], data, 20);
GET_UINT32_BE(W[6], data, 24);
GET_UINT32_BE(W[7], data, 28);
GET_UINT32_BE(W[8], data, 32);
GET_UINT32_BE(W[9], data, 36);
GET_UINT32_BE(W[10], data, 40);
GET_UINT32_BE(W[11], data, 44);
GET_UINT32_BE(W[12], data, 48);
GET_UINT32_BE(W[13], data, 52);
GET_UINT32_BE(W[14], data, 56);
GET_UINT32_BE(W[15], data, 60);
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) { \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98);
P(H, A, B, C, D, E, F, G, W[1], 0x71374491);
P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF);
P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5);
P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B);
P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1);
P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4);
P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5);
P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98);
P(H, A, B, C, D, E, F, G, W[9], 0x12835B01);
P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
Expect the hashing time to be withing a few seconds, not 100sec.
The difference in performance you did notice may be caused by one of both of the CPU Instructions/Data caches being disabled.
You can enable/disable both caches from u-boot provided that it was compiled with the icache/dcache commands.
If your u-boot does not already include the icache/dcache commands, you may have to re-compile it after having added the following line to the configuration file: CONFIG_CMD_CACHE=y.
Another option would be to enable it in your code programmatically prior to start computing the hash.
I have a List of case objects of which some values are NaNs and I have to replace them with 0.0. So far I tried this code:
var systemInformation: List[SystemInformation] = (x.getIndividualSystemInformation)
systemInformation.foreach[SystemInformation] {
_ match {
case SystemInformation(a, b, c, d, e, f, g, h, i, j, k, l, m, x) if x.isNaN()
=> SystemInformation(a, b, c, d, e, f, g, h, i, j, k, l, m, 0.0)
case SystemInformation(a, b, c, d, e, f, g, h, i, j, k, l, m, x) if !x.isNaN()
=> SystemInformation(a, b, c, d, e, f, g, h, i, j, k, l, m, x)
}
}
But that does not write the changes back to systemInformation. So I added another List but got a type mismatch:
var systemInformation: List[SystemInformation] = (x.getIndividualSystemInformation)
var systemInformationWithoutNans: ListBuffer[SystemInformation] = new ListBuffer[SystemInformation]
systemInformation.foreach[SystemInformation] {
_ match {
case SystemInformation(a, b, c, d, e, f, g, h, i, j, k, l, m, x) if x.isNaN()
=> systemInformationWithoutNans += SystemInformation(a, b, c, d, e, f, g, h, i, j, k, l, m, 0.0)
case SystemInformation(a, b, c, d, e, f, g, h, i, j, k, l, m, x) if !x.isNaN()
=> SystemInformation(a, b, c, d, e, f, g, h, i, j, k, l, m, x)
}
}
The error occurs on the line with the += and is the following:
type mismatch;
found : scala.collection.mutable.ListBuffer[com.x.interfaces.SystemInformation]
required: com.x.interfaces.SystemInformation
Why does this not work? What would be a better way to replace the NaNs with 0.0?
Use map as bluenote10 sugested, but additionally, what about:
val transformedSystemInformation = systemInformation map (_ match {
case s:SystemInformation if s.x.isNan() => s.copy(x = 0.0)
case _ => _
})
You should use map instead of foreach.
Your first solution is basically the right way to go, but foreach only iterates over all elements, whereas map allows to map the elements from type A to B returning a new collection of type B.
Since your first question is not answered above, I thought I would add that this doesn't work, because the method +=
def +=(x: A): ListBuffer.this.type
returns a ListBuffer[SystemInformation] in this case, but you have parameterized foreach by the type SystemInformation
foreach[SystemInformation]
which is why the compiler is expecting the type SystemInformation rather than ListBuffer[SystemInformation] and returns the error
type mismatch;
found : scala.collection.mutable.ListBuffer[com.x.interfaces.SystemInformation]
required: com.x.interfaces.SystemInformation
If, on the other hand, you remove the type parameterization from foreach, your example will compile:
...
systemInformation.foreach { ... }
...
For a better approach, used Ian McMahon's suggested approach.
I'd like to create a Set of character ranges in Scala, something like A..Za..z0..9. Here's my take:
scala> ('A' to 'Z').toSet.union(('a' to 'z').toSet).union(('0' to '9').toSet)
res3: scala.collection.immutable.Set[Char] = Set(E, e, X, s, x, 8, 4, n, 9, N, j, y, T, Y, t, J, u, U, f, F, A, a, 5, m, M, I, i, v, G, 6, 1, V, q, Q, L, b, g, B, l, P, p, 0, 2, C, H, c, W, h, 7, r, K, w, R, 3, k, O, D, Z, o, z, S, d)
This can't be the idiomatic way to do this. What's a better way?
How about this:
scala> ('a' to 'z').toSet ++ ('A' to 'Z') ++ ('0' to '9')
res0: scala.collection.immutable.Set[Char] = Set(E, e, X, s, x, 8, 4, n, 9, N, j, y, T, Y, t, J, u, U, f, F, A, a, 5, m, M, I, i, v, G, 6, 1, V, q, Q, L, b, g, B, l, P, p, 0, 2, C, H, c, W, h, 7, r, K, w, R, 3, k, O, D, Z, o, z, S, d)
Or, alternatively:
scala> (('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')).toSet
res0: scala.collection.immutable.Set[Char] = Set(E, e, X, s, x, 8, 4, n, 9, N, j, y, T, Y, t, J, u, U, f, F, A, a, 5, m, M, I, i, v, G, 6, 1, V, q, Q, L, b, g, B, l, P, p, 0, 2, C, H, c, W, h, 7, r, K, w, R, 3, k, O, D, Z, o, z, S, d)
('0' to 'z').filter(_.isLetterOrDigit).toSet
A more functional version of your code is this:
scala> Traversable(('A' to 'Z'), ('a' to 'z'), ('0' to '9')) map (_ toSet) reduce (_ ++ _)
Combining it with the above solutions, one gets:
scala> Seq[Seq[Char]](('A' to 'Z'), ('a' to 'z'), ('0' to '9')) reduce (_ ++ _) toSet
If you have just three sets, the other solutions are simpler, but this structure also works nicely if you have more ranges or they are given at runtime.
I guess it can't be simpler than this:
('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')
You might guess that ('A' to 'z') will include both, but it also adds some extra undesirable characters, namely:
([, \, ], ^, _, `)
Note:
This will not return a Set but an IndexedSeq. I assumed you don't mind the implementation, but if you do, and do want a Set, just call toSet to the result.
If you want to generate all the possible characters, doing this should generate all the values a char can take:
(' ' to '~').toSet